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
相关产品推荐
相关产品推荐

