反应:错误:重新渲染太多。 React 限制渲染次数以防止无限循环

时间:2021-04-19 13:06:01

标签: javascript reactjs react-hooks

这是我第一次使用 stackoverflow,很高兴认识你们。我很新来反应。我正在尝试使用我刚刚构建的天气应用程序学习钩子,但我收到了太多的重新渲染错误。该应用程序与类组件一起工作得很好。我尝试在箭头函数中包装 handleInputChange 但随后应用程序甚至没有调用 api

这是代码:

import React, { useState } from "react";
import axios from "axios";
import "./App.css";

const dateBuilder = (today) => {
  let months = [
    "January",
    "February",
    "March",
    "April",
    "May",
    "June",
    "July",
    "August",
    "September",
    "October",
    "November",
    "December",
  ];
  let days = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
  ];
  let day = days[today.getDay()];
  let date = today.getDate();
  let month = months[today.getMonth()];

  return `${day} ${date} ${month}`;
};

const key = process.env.REACT_APP_WEATHER_API_KEY;

const App = () => {

  const [info, setInfo] = useState([]);

  const [background, setBackground] = useState("app");

  const handleInputChange = (event) => {
    console.log('event', event)
    if (event.key === "Enter") {
      const city = event.target.value;
      const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`;

      axios
        .get(apiUrl)
        .then((res) => {
          const { data } = res;
          console.log("api response", res);

            setInfo(data);
          console.log("info", info);
        })

        .catch((err) => console.log("err", err));
    }
  };

  if (info.weather) {
    switch (info.weather[0].main) {
      case "Rain":
        setBackground("rain");
        break;
      case "Clouds":
        setBackground("clouds");
        break;
      case "Snow":
        setBackground("snow");
        break;
      case "Fog":
        setBackground("fog");
        break;
      case "Drizzle":
        setBackground("drizzle");
      case "Thunderstorm":
        setBackground("thunderstorm");
      case "Clear":
        setBackground("app");
        break;
    }
  }

  return (
    <div className={background}>
      <main>
        <div className="search-box">
          <input
            type="text"
            className="search-bar"
            placeholder="search..."
            onKeyPress={handleInputChange}
          />
        </div>
        <div className="location-box">
          <div className="location">{info.name}</div>
          <div className="date">{dateBuilder(new Date())}</div>
        </div>
        {typeof info.main != "undefined" ? (
          <div>
            <div className="weather-box">
              <div className="temp">
                {Math.round(info.main.temp - 273.15)}º C
              </div>

              <div className="weather">{info.weather[0].main}</div>
              <div className="pressure">{info.main.pressure} mbar</div>
              <div className="pressure">{info.main.humidity} % humidity</div>
            </div>
          </div>
        ) : (
          <></>
        )}
      </main>
    </div>
  );
};

export default App;

1 个答案:

答案 0 :(得分:1)

嗨,欢迎来到 stackoverflow 社区!

在这种情况下,您需要使用效果! 由于您的 switch 语句,您的组件一次又一次地循环。

如果 setBackground 存在,则在每次渲染时调用

info.weather。但是调用 setBackground 也会触发一个新的渲染。您需要的是取决于 info

值的效果
const App = () => {

  const [info, setInfo] = useState([]);

  const [background, setBackground] = useState("app");

  useEffect(() => {
    if (info.weather) {
      switch (info.weather[0].main) {
        case "Rain":
          setBackground("rain");
          break;
        case "Clouds":
          setBackground("clouds");
          break;
        case "Snow":
          setBackground("snow");
          break;
        case "Fog":
          setBackground("fog");
          break;
        case "Drizzle":
          setBackground("drizzle");
        case "Thunderstorm":
          setBackground("thunderstorm");
        case "Clear":
          setBackground("app");
          break;
      }
    }}, [info])

  const handleInputChange = (event) => {
    console.log('event', event)
    if (event.key === "Enter") {
      const city = event.target.value;
      const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${key}`;

      axios
        .get(apiUrl)
        .then((res) => {
          const { data } = res;
          console.log("api response", res);

            setInfo(data);
          console.log("info", info);
        })

        .catch((err) => console.log("err", err));
    }
  };

  return (
    <div className={background}>
      <main>
        <div className="search-box">
          <input
            type="text"
            className="search-bar"
            placeholder="search..."
            onKeyPress={handleInputChange}
          />
        </div>
        <div className="location-box">
          <div className="location">{info.name}</div>
          <div className="date">{dateBuilder(new Date())}</div>
        </div>
        {typeof info.main != "undefined" ? (
          <div>
            <div className="weather-box">
              <div className="temp">
                {Math.round(info.main.temp - 273.15)}º C
              </div>

              <div className="weather">{info.weather[0].main}</div>
              <div className="pressure">{info.main.pressure} mbar</div>
              <div className="pressure">{info.main.humidity} % humidity</div>
            </div>
          </div>
        ) : (
          <></>
        )}
      </main>
    </div>
  );
};

关于效果的更多信息:https://reactjs.org/docs/hooks-effect.html