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

React useEffect中fetch获取数据后setState状态始终为null问题

问题核心原因

React 函数组件的状态更新是异步批处理机制,setProducts(data) 不会同步修改当前作用域下的 products 变量,只会触发组件重新渲染,新的状态值只会在下一次渲染生成的新闭包中生效。
你在调用setProducts(data)之后立刻执行console.log(products),读到的是当前渲染闭包里缓存的初始状态值null,这完全是闭包特性导致的正常现象,你的setState调用本身已经成功执行了,数据已经正确存入状态,只是打印的时机和位置不对,才会误以为赋值失败。

正确验证状态更新的方法

不要在setState调用的同一段同步逻辑里读取新状态,新增一个依赖products的useEffect,就能在状态更新后拿到最新值:

const [products, setProducts] = useState(null);

// 专门监听products变化,状态更新后会自动执行
useEffect(() => {
  console.log('状态更新后的products值:', products);
}, [products])

useEffect(() => {
  fetch('http://127.0.0.1:8000/api_products/')
    .then(res => res.json())
    .then((data) => {
      console.log('接口返回原始数据:', data);
      setProducts(data);
      // 此处打印的是当前闭包的旧值,永远为初始null,不代表赋值失败
    })
}, [])
页面渲染适配

因为products初始值为null,直接调用products.map会抛出类型错误,渲染时需要先做空值判断:

return (
  <div className="product-container">
    {
      !products ?
      <p>商品数据加载中...</p> :
      products.map(product => (
        <div key={product.id} className="product-item">
          <img src={product.image} alt={product.name} />
          <h4>{product.name}</h4>
          <p>配送规则:{product.shipping}</p>
        </div>
      ))
    }
  </div>
)
避坑提示
  • 函数组件中所有状态值在单次渲染周期内是固定不变的,setState触发的更新只会在下一次渲染体现
  • 不要依赖setState之后同步读取状态做逻辑判断,需要基于最新状态执行的逻辑,要么写到对应状态的useEffect回调里,要么用函数式setState写法
  • 你当前的接口请求、响应解析、setState传参逻辑都没有错误,不需要调整请求相关代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:33:15