React使用axios获取数据时访问questionText报undefined错误
问题根源
报错和接口返回的JSON结构无关,是代码里的React执行逻辑错误:
- 普通局部变量修改不会触发组件重渲染:你初始化
questions为空数组,组件首次渲染时会直接执行到questions[currentQuestion].questionText这行,此时questions[0]是undefined,读取undefined的属性直接抛出Cannot read properties of undefined错误。静态注释数据之所以正常,是因为变量初始化时就带了完整题目内容,首次渲染就能读到对应值。 - 接口请求直接写在组件函数体中,每次组件重渲染都会重复发起请求,就算后续改用变量存值也会导致无限重渲染、请求死循环。
- 之前改用类组件state仍复现错误,核心是没做加载态兜底:接口请求是异步的,首次渲染时state里的题目数组还是空的,没等数据返回就去读数组项的属性,一样会抛错。
修复方案
按以下步骤改代码即可:
- 引入副作用钩子,将题目数据改为响应式state
把react的引入行改成:
替换原来的import { useState, useEffect } from "react";var questions = []为state定义:const [questions, setQuestions] = useState([]); const [currentQuestion, setCurrentQuestion] = useState(0); const [popup, setPopup] = useState(false); - 把接口请求移到
useEffect中,仅在组件首次挂载时执行,拿到数据后通过state方法更新,触发组件重渲染:
删掉原来直接写在函数体里的useEffect(() => { axios.get('http://localhost/getQuestions.php',{withCredentials: true}) .then(res => { // 若接口返回结构是带code/msg的包裹层,此处取对应层级即可,比如res.data.data setQuestions(res.data); }) }, []);getData()调用和普通的getData函数定义。 - 增加加载态兜底,在题目数据没加载完成时不渲染题目区域,从根源避免空值读取错误:
把return中原来的.main-quiz区块替换为如下逻辑:
这里顺便修复两个原有逻辑bug:<div className="main-quiz"> {questions.length === 0 ? ( <div className="loading">题目加载中,请稍候...</div> ) : ( <> <div className="progressbar" ></div> <div className="question">{questions[currentQuestion].questionText}</div> <div className="answers"> {questions[currentQuestion].answerOptions.map((answerOption, idx) =>( <button key={idx} onClick={() => handleButtonClick(answerOption.isCorrect)}> <div className="choice">{answerOption.answerText}</div> </button> ))} </div> </> )} </div>- 列表遍历增加
key属性,消除React渲染警告 - 原代码的
onClick={handleButtonClick}没有传入当前选项的isCorrect参数,判分逻辑永远拿不到正确值,改为箭头函数包裹传参
- 列表遍历增加
- 校验接口返回层级:如果按上述修改后加载完成仍报错,直接在axios的then回调里打印
res.data,确认是否拿到的是直接的题目数组。部分PHP接口会返回带状态码的包裹结构(比如{code:200, data: [题目数组]}),这种情况需要取res.data.data传给setQuestions。
内容的提问来源于stack exchange,提问作者Turgut Güvercin
相关产品推荐
相关产品推荐

