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

React中Fetch拼接模板字符串URL偶发失效返回空数组

问题根因

你的代码存在三个核心问题,直接对应你遇到的异常现象:

  • 请求触发时机混乱:useEffect传入空依赖数组,只会在组件首次挂载时执行1次;同时你在effect外部定义的getWeather是每次组件重渲染都会重新生成的函数,空依赖捕获的是首次渲染时的函数闭包,属于典型的React闭包陷阱,才会出现只有意外重渲染才偶尔发起请求的情况。
  • 初始值类型不匹配:weatherData初始值设为空数组,而OpenWeather天气接口返回的是对象结构,首次渲染时子组件拿到的是空数组展开后的空属性,看起来就像没有返回数据。
  • 请求错误无感知:你的代码没有校验接口响应状态,加上如果请求地址里的参数分隔符误写为HTML转义字符&,会导致接口参数解析失败,请求出错时只会静默打印控制台日志,不会更新页面状态,进一步放大了“返回空数组”的错觉。
修复方案

推荐把请求逻辑收拢到useEffect内部,从根源规避闭包问题,同时补全状态兜底逻辑,修复后代码如下:

import './App.css';
import Daily from './components/daily';
import {useState, useEffect} from 'react'

function App() {
  const [city, setCity] = useState('London')
  // 初始值设为null,方便区分初始加载状态和接口返回状态
  const [weatherData, setWeather] = useState(null)
  const [loading, setLoading] = useState(true)
  const [errorMsg, setErrorMsg] = useState('')

  useEffect(()=>{
    const getWeather = async() =>{
      try{
        setLoading(true)
        // 注意参数分隔符用&,不要用HTML转义的&
        const resp = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=f8d957da06af592a1390c360ea801908&units=metric`)
        // 先校验HTTP响应状态,再解析JSON
        if (!resp.ok) throw new Error('天气数据请求失败,请检查配置')
        const data = await resp.json()
        setWeather(data)
        setErrorMsg('')
      }catch(err){
        setErrorMsg(err.message)
        console.error('请求异常:', err)
      }finally{
        setLoading(false)
      }
    }
    getWeather()
    // 把city加入依赖数组,首次挂载、city变更时都会自动触发请求
  }, [city])

  // 加载和错误状态兜底
  if (loading) return <div>正在加载天气数据...</div>
  if (errorMsg) return <div>加载失败:{errorMsg}</div>

  return(
    <>
      {weatherData && <Daily {...weatherData} />}
    </>
  )
}

export default App;
关键修改说明
  • 将异步请求函数移到useEffect内部,消除跨作用域的闭包引用问题
  • 给useEffect添加city作为依赖项,保证请求触发时机符合预期,不会出现偶发不执行的问题
  • 修正请求地址的参数分隔符,新增HTTP响应状态校验,避免接口返回错误时静默失败
  • 新增加载、错误状态兜底,调整weatherData初始值类型匹配接口返回结构,避免首次渲染传入无效空数据
  • 增加数据存在性判断,确认接口返回有效数据后再传入子组件渲染

如果你后续需要在effect外部手动触发请求刷新,可以用useCallback包裹getWeather函数后再加入useEffect的依赖数组,不要在空依赖的effect里直接引用外部定义的普通函数,否则很容易再次触发闭包陷阱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:39:13