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

React useEffect中使用async/Promise时setState异步取值为空问题

问题原因
  • React 函数组件里useState返回的状态更新函数不是Promise对象,前面加await不会产生等待效果,状态更新是批量异步调度的,不会在当前执行上下文里立刻完成。
  • 函数组件每一次渲染都会生成独立的闭包,你在fetchQuestions函数里最后返回的questionsArray,永远是当前渲染闭包中保存的初始值(也就是定义状态时设置的初始值null/空数组),哪怕后续状态更新触发重渲染,当前闭包里的这个变量也不会发生变化。
  • useEffect初次执行时拿到的questionsArray也是首次渲染闭包里的初始值,你在then回调里判断questionsArray.length,本质是在判断永远不会变的初始值,自然拿不到有效结果。
修复代码

直接在数据处理阶段拿到最终结果传递,不要绕一圈等状态更新后再从闭包里取值:

  1. 改造fetchQuestions函数,提前计算好处理后的数据,直接返回计算结果,不要返回闭包内的状态,也不需要给setter加await:
const fetchQuestions = async () => {
  const data = require("../../question.json");
  // 提前处理两份需要存入状态的数据
  const questionList = data.map((item: IQuestion) => ({
    id: item.id,
    question: item.question,
    answers: item.answers
  }));
  const questionArrayList = data.map((item: IQuestion) => ({
    id: item.id,
    name: item.question
  }));
  // 触发状态更新,不需要await
  setQuestions(questionList);
  setQuestionsArray(questionArrayList);
  // 直接返回处理好的数组,不要从状态里取值
  return questionArrayList;
}
  1. 调整useEffect逻辑,直接使用Promise返回的处理结果做判断,不要依赖闭包内的旧状态:
useEffect(() => {
  if (nick.length < 1) {
    navigate('/quiz');
    return;
  }
  fetchQuestions().then((res)=>{
    if (res.length > 0){
      handleQuest(res);
    } else {
      console.log("Nothing")
    }
  })
}, []);

补充说明:如果后续场景必须要等状态更新完成后再执行逻辑,不要给setter加await,应该单独新增一个依赖对应状态的useEffect监听状态变化,比如:

useEffect(() => {
  if (questionsArray.length > 0) {
    handleQuest(questionsArray)
  }
}, [questionsArray])

但当前场景不需要这么写,数据处理阶段已经拿到了最终值,直接传递即可,多写监听useEffect反而会产生冗余执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 08:09:15