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

如何将API数据设置到React state中并避免无限重渲染问题

问题原因

你将Axios天气请求直接放在了渲染执行的limitSearchArray函数内,每次组件渲染都会触发请求,请求成功调用setWeather修改状态后,又会触发组件重新渲染,进入「渲染→发请求→改状态→重渲染」的无限循环。

解决方法

把天气请求逻辑抽离到useEffect中,仅当需要查询的城市变化时才发起一次请求,具体修改如下:

  1. 把国家过滤逻辑从渲染函数中抽离,作为useEffect的依赖项
  2. 仅当筛选出唯一国家时,才触发一次天气接口请求
  3. 移除渲染函数中的请求逻辑,避免重复触发状态更新

修改后的完整代码:

import React, { useState, useEffect} from 'react'
import axios from 'axios' // 原代码漏了axios导入,这里补全
import './App.css'

const api_key = process.env.REACT_APP_API_KEY_WEATHER_API

const App = () => {
  const [countries, setCountries] = useState([])
  const [countrySearch, setCountrySearch] = useState('')
  const [weather, setWeather] = useState(
      {
        current:{
          temp_c:'', 
          condition:{icon: ''},
          wind_mph: '', 
          wind_dir: ''
        }
      }
    )

  const hook = () => {
    axios
      .get('https://restcountries.eu/rest/v2/all')
      .then(response => setCountries(response.data))
  }
  useEffect(hook, [])

  // 抽离国家过滤逻辑,方便作为依赖项
  const filteredCountries = countries.filter(country => 
    country.name.toLowerCase().indexOf(countrySearch.toLowerCase()) !== -1
  )

  // 新增天气请求useEffect,仅依赖项变化时才执行
  useEffect(() => {
    // 仅当筛选出唯一国家时才发起天气请求
    if (filteredCountries.length === 1) {
      const capital = filteredCountries[0].capital
      axios
      .get(`http://api.weatherapi.com/v1/current.json?key=${api_key}&q=${capital}&aqi=no`)
      .then(response => setWeather(response.data))
    }
  }, [filteredCountries, api_key])
  
  const countrySearchHandler = (event) => {
    setCountrySearch(event.target.value)
  }

  const handleShowCountry = (event) => {
    setCountrySearch(event.target.value)
  }

  const limitSearchArray = () => {
    if (filteredCountries.length === 1) {
      const country = filteredCountries[0]
      // 移除了原代码这里的请求逻辑,仅保留渲染逻辑
      return (
        <div>
          <h1>{country.name}</h1>
          <p>capital {country.capital}</p>
          <p>population {country.population}</p>
          <h2>languages</h2>
          <ul>
            {country.languages.map(language => 
              <li key={language.name}>{language.name}</li>)}
          </ul>
          <img src={country.flag} alt={country.name} height='100px'/>
          <h2>Weather in {country.capital}</h2>
              <p>temperature: {weather.current.temp_c} Celcius</p>
              <img src={weather.current.condition.icon} alt={country.capital}/>
              <p>wind: {weather.current.wind_mph} mph direction {weather.current.wind_dir}</p>
        </div>
      )
    } else if (filteredCountries.length <= 10){
        return (
          filteredCountries.map(country => 
          <p key={country.name}>{country.name}
            <button value={country.name} onClick={handleShowCountry}>show</button>
          </p>)
        )
    } else {
        return 'Too many matches, specify another filter'
    }
  }

  return (
    <div>
      find countries <input value={countrySearch} onChange={countrySearchHandler}></input>
      <div>
        {limitSearchArray()}
      </div>
    </div>
  )
}

export default App

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 19:27:04