reactjs 显示错误:React中的重新渲染太多

xcitsw88  于 2023-02-12  发布在  React
关注(0)|答案(1)|浏览(145)

这是我编写的代码,用于根据用户输入更改背景视频。背景具有基于用户输入位置的天气的视频。

import React, { Fragment, useState, useEffect } from "react";
import cloudy from "../assets/cloudy.mp4";
import sunny from "../assets/sunny.mp4";
import rainy from "../assets/rainy.mp4";
import winter from "../assets/winter.mp4";

const weathers = [cloudy, sunny, rainy, winter];

const Background = (props) => {
const [weather, setWeather] = useState(weathers[1]);

const temp = props.info.current.temp_c;
const rain = props.info.current.precip_mm;

if (rain > 2.5) setWeather(weathers[2]);
else if (temp < 8) setWeather(weathers[3]);

return (
  <Fragment>
    <video autoPlay loop muted className="back-video">
      <source src={weather} type="video/mp4" />
    </video>
  </Fragment>
  );
}

下面是我在App组件中的返回方式:

return (
<Fragment>
  <div className="container">
    <h1>Weather App</h1>
    <Input newLocation={locationHandler} />
    <article>{content}</article>
  </div>
  <article>{background}</article>
</Fragment>
)

我尝试使用UseEffect,因为我有一个重新渲染错误,但在这种情况下,它根本不会改变背景

useEffect(() => {
 if (rain > 2.5) setWeather(weathers[2]);
 else if (temp < 8) setWeather(weathers[3]);
}, [weather, temp, rain])

或者仅将天气作为依赖项。
编辑:我的应用程序组件

import React, { useState, useEffect, useCallback, Fragment } from 
"react";
import Background from "./components/Background";
import Weather from "./components/Weather";
import Input from "./UI/Input";

function App() {
  const [weather, setWeather] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  const [location, newLocation] = useState("New Delhi");

  const locationHandler = (place) => {
    newLocation(place);
  };

  const fetchweatherHandler = useCallback(async () => {
    setIsLoading(true);
    setError(null);
  try {
  //console.log(location);
  const response = await fetch(
    `http://api.weatherapi.com/v1/current.json? 
 key={apiKey}&q=${location}&aqi=yes`
  );

  if (!response.ok) {
    throw new Error("Something went wrong!");
  }

  const data = await response.json();
  //console.log(data);
  setWeather(data);
    } catch (error) {
  setError(error.message);
    }
setIsLoading(false);
  }, [location]);

  useEffect(() => {
fetchweatherHandler();
  }, [fetchweatherHandler]);

  let content = <p>Found no weather.</p>;
  let background = <p>No Background</p>;

  if (weather && Object.keys(weather).length > 0) {
    content = weather && <Weather info={weather} />;
    background = weather && <Background info={weather} />;
  }

  if (error) {
    content = <p>{error}</p>;
  }

  if (isLoading) {
    content = <p>Loading...</p>;
  }

  return (
<Fragment>
  <div className="container">
    <h1>Weather App</h1>
    <Input newLoc={locationHandler} />
    <article>{content}</article>
  </div>
  <article>{background}</article>
</Fragment>
  );
}

export default App;
0lvr5msh

0lvr5msh1#

UseEffect的工作原理是这样的:无论你在[]中传递了哪个状态,useEffect都会监听它的状态,只要状态发生变化,它就会执行useEffect中的代码。
在你的例子中,你传递了[weather],在useEffect中你改变了setWeather,这改变了weather,所以useEffect再次运行,这又是weather的集合,它继续导致无限循环,并导致太多的重新呈现错误。
您可以像下面这样使用它,但它不会在每次天气变化时重新渲染。

useEffect(() => {
 if (rain > 2.5) setWeather(weathers[2]);
 else if (temp < 8) setWeather(weathers[3]);
}, [temp, rain])

查看主题lifecycle of components in react functional components了解更多信息

相关问题