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

React setState后打印空数组 重渲染后才显示State值问题

问题本质

你的判断是对的,问题出在React状态更新机制和闭包特性上:

  • React中setState调用是异步批处理的,不会同步修改当前作用域内的state变量
  • 首次执行useEffect时,回调函数里的闭包捕获的是初始渲染时的curse值(也就是空数组)
  • 调用setCurse触发重渲染后,新的curse值才会在新的渲染周期对应的作用域中生效,所以你在setCurse后立刻打印,拿到的永远是闭包缓存的旧初始值。
可行解决方案

方案1:直接打印接口处理后的临时值(最常用)

你从数据库拉取数据后map得到的结果本身就是要存入state的值,不需要等state更新再打印,直接输出临时变量即可:

const [curse, setCurse] = useState([]);
const usersCollectionRef = collection(db, "curse");

useEffect(() => {
  const getUsers = async () => {
    const data = await getDocs(usersCollectionRef);
    const resolvedCurseList = data.docs.map((doc) => ({ ...doc.data(), id: doc.id }));
    setCurse(resolvedCurseList);
    // 直接打印处理好的临时值,立刻就能拿到正确结果
    console.log(resolvedCurseList);
  };

  getUsers();
}, []);

方案2:单独监听state变化执行后续逻辑

如果你的业务逻辑必须依赖state更新后的值,可以单独写一个依赖项为curse的useEffect,每次curse更新重渲染后都会触发这里的逻辑:

const [curse, setCurse] = useState([]);
const usersCollectionRef = collection(db, "curse");

// 拉取数据的effect逻辑保持不变
useEffect(() => {
  const getUsers = async () => {
    const data = await getDocs(usersCollectionRef);
    setCurse(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
  };
  getUsers();
}, []);

// 单独监听curse变化,值更新后自动执行
useEffect(() => {
  console.log(curse);
  // 所有依赖最新curse值的逻辑都可以写在这里
}, [curse]);

注意:不要把curse加到拉取数据的那个useEffect的依赖数组里,会导致重复触发接口请求,引发死循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:27:45