React使用状态值作为数组索引访问对象key出现undefined问题
问题原因
- 初始状态取值异常:组件首次渲染时,fetch请求还在异步执行,
displaySingleQuestion的初始值是空数组[],此时取displaySingleQuestion[questionNumber](也就是[][0])得到的是undefined。而你currentQuestion的初始值是空字符串,不管是undefined还是空字符串,访问.question属性都会得到undefined。 - 控制台打印的引用特性误导:你直接打印
currentQuestion时,浏览器控制台输出的是对象的引用,等你手动展开查看时,fetch请求已经完成、state已经更新,所以能看到完整的对象结构;但打印currentQuestion.question时取的是代码执行那一刻的快照,此时值还没更新,自然输出undefined。 - useEffect依赖项缺失:你第二个用来更新
currentQuestion的useEffect只监听了displaySingleQuestion,后续如果questionNumber变化(比如用户切换题目),currentQuestion不会同步更新,会一直停留在第一个题目。
你觉得固定索引0可以正常显示,是因为fetch完成后组件重渲染,此时数组已经有值,索引0存在所以能正常读取,本质上首次渲染时同样会遇到取值undefined的问题,只是没有持续影响显示效果。
修复方案
- 给取值操作加安全判断,用可选链
?.避免未加载完成时报错 - 补全useEffect的依赖项,加入
questionNumber - 可以加加载状态避免白屏或者异常显示
修复后的代码参考:
function DisplaySingleQuestion() { const [displaySingleQuestion, setDisplaySingleQuestion] = useState([]); const [questionNumber, setQuestionNumber] = useState(0); // 初始值设为undefined更合理 const [currentQuestion, setCurrentQuestion] = useState(undefined); useEffect(() => { fetch("./database/questions.json") .then(async resp => await resp.json()) .then(data => setDisplaySingleQuestion(data.questions)) .catch(err => console.log(err)) }, []); // 依赖项加入questionNumber,保证题号变化时同步更新当前题目 useEffect(() => { // 加判断,数组有对应索引值时才更新 if (displaySingleQuestion.length > questionNumber) { setCurrentQuestion(displaySingleQuestion[questionNumber]) } }, [displaySingleQuestion, questionNumber]); // 加载完成前显示加载提示 if (!currentQuestion) return <div>加载中...</div> return ( <div> <p>to jest Single Question</p> <div style={{backgroundColor: "red"}}> <p>{currentQuestion.question}</p> {/* 也可以直接去掉currentQuestion相关逻辑,用可选链直接取值: <p>{displaySingleQuestion[questionNumber]?.question}</p> */} </div> </div> ) }
内容的提问来源于stack exchange,提问作者Anna B
相关产品推荐
相关产品推荐

