You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hooks天气应用出现Too many re-renders无限循环错误的技术求助

Fixing the "Too many re-renders" Error in Your React Weather App

Hey there! Let's break down why you're hitting that frustrating error and get your weather app working smoothly with Hooks.

What's Causing the Infinite Re-Renders?

The problem is right here in your component's top-level code:

if (info.weather) {
  switch (info.weather[0].main) {
    // ... your case statements calling setBackground
  }
}

Every time your component renders (which happens every time you update state, like when setInfo runs after the API call), this block executes. Calling setBackground updates state, which triggers another render... which runs this block again, and so on. It's an infinite loop!

The Fix: Use useEffect for State-Dependent Updates

We need to move that background-switching logic into a useEffect hook. This hook lets us run code only when specific dependencies change, instead of on every render.

Here's how to adjust your code:

  1. First, add useEffect to your React imports:
import React, { useState, useEffect } from "react";
  1. Replace your top-level if/switch block with this useEffect:
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");
        break; // Fixed missing break here!
      case "Thunderstorm":
        setBackground("thunderstorm");
        break; // Fixed missing break here too!
      case "Clear":
        setBackground("app");
        break;
      default:
        setBackground("app"); // Add a default to handle unexpected weather types
    }
  }
}, [info]); // Only run this effect when `info` changes

Notice I also fixed missing break statements in your switch cases—without those, a "Drizzle" weather type would fall through to the "Thunderstorm" case and overwrite your background setting!

Full Modified Code

Here's your complete app code with all fixes applied:

import React, { useState, useEffect } 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) => {
    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;
          setInfo(data);
        })
        .catch((err) => console.log("err", err));
    }
  };

  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");
          break;
        case "Thunderstorm":
          setBackground("thunderstorm");
          break;
        case "Clear":
          setBackground("app");
          break;
        default:
          setBackground("app");
      }
    }
  }, [info]);

  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="humidity">{info.main.humidity} % humidity</div>
              {/* Fixed duplicate class name here too! */}
            </div>
          </div>
        ) : (
          <></>
        )}
      </main>
    </div>
  );
};

export default App;

Quick Notes

  • I also fixed a duplicate pressure class name on your humidity element—small detail, but it'll keep your CSS working as expected.
  • Remember: never call state setters (like setBackground or setInfo) directly in the component's top-level render code. Always use useEffect for updates that depend on other state/props.

内容的提问来源于stack exchange,提问作者cypher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 14:27:38