ReactJS Quiz App调用API获取题目后无法展示的技术求助
ReactJS答题应用初始化渲染错误解决方案
问题描述
开发基于API的ReactJS答题应用,玩家选择难度级别后通过Redux存储,进入Questionnaire页面根据级别获取题目。但组件初始化展示题目时出现错误,单独测试API可正常返回非空数据。
用户代码
import React, { useState, useEffect } from "react"; import { connect } from "react-redux"; import "../App.css"; import "bootstrap/dist/css/bootstrap.min.css"; function Questionnaire(props) { console.log("questionnaire", props.saveLevel); const [quizList, setQuizList] = useState([]); const [currentQuestion, setCurrentQuestion] = useState(0); useEffect(() => { const getQuiz = async () => { const data = await fetch(`/quiz?level=${props.saveLevel}`; const body = await data.json(); setQuizList(body.quizQuestion); }; getQuiz(); }, []); console.log("quizinfos", quizList); const handleClickAnswer = () => { setCurrentQuestion(currentQuestion + 1); }; return ( <div className="MainContainer"> {console.log("hello")} <h4>Welcome to questionnaire</h4> <div> <h6>{quizList[currentQuestion].questionText}</h6> <div> {quizList[currentQuestion].answers.map((element) => { return ( <button onClick={() => handleClickAnswer()}> {element.answerText} </button> ); })} </div> </div> </div> ); } function mapStateToProps(state) { return { saveLevel: state.saveLevel }; } export default connect(mapStateToProps, null)(Questionnaire);
控制台输出
questionnaire 1 Questionnaire.js:26 quizinfos [] Questionnaire.js:33 hello Questionnaire.js:37 Uncaught TypeError: Cannot read properties of undefined (reading 'questionText') react-dom.development.js:18687 The above error occurred in the <Questionnaire> component: Questionnaire.js:37 Uncaught TypeError: Cannot read properties of undefined (reading 'questionText')
错误原因分析
- 初始状态访问undefined:组件初始化时
quizList是空数组,quizList[0]为undefined,直接访问.questionText会触发类型错误。 - fetch语法错误:
fetch调用末尾缺失闭合括号,会导致请求无法正常执行。 - useEffect依赖缺失:依赖数组为空,当
props.saveLevel变化时不会重新触发API请求;若组件初始化时props.saveLevel未同步获取到,也会导致请求参数异常。
修复步骤
- 添加加载状态:在数据未返回时显示加载提示,避免访问未定义的属性。
- 修复fetch语法错误:补上
fetch调用末尾的闭合括号。 - 完善useEffect依赖:将
props.saveLevel加入依赖数组,确保级别变化时重新请求数据。 - 添加边界检查:确保
currentQuestion不超出题目数量范围,避免切换题目时出现越界错误。 - 可选:添加错误处理:捕获API请求可能出现的异常,提升用户体验。
修改后的完整代码
import React, { useState, useEffect } from "react"; import { connect } from "react-redux"; import "../App.css"; import "bootstrap/dist/css/bootstrap.min.css"; function Questionnaire(props) { console.log("questionnaire", props.saveLevel); const [quizList, setQuizList] = useState([]); const [currentQuestion, setCurrentQuestion] = useState(0); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const getQuiz = async () => { try { setIsLoading(true); // 修复fetch语法错误:补上闭合括号 const data = await fetch(`/quiz?level=${props.saveLevel}`); if (!data.ok) throw new Error("请求失败"); const body = await data.json(); setQuizList(body.quizQuestion); setError(null); // 重置当前题目索引到第一题 setCurrentQuestion(0); } catch (err) { setError(err.message); setQuizList([]); } finally { setIsLoading(false); } }; // 只有当saveLevel存在时才发起请求 if (props.saveLevel) { getQuiz(); } }, [props.saveLevel]); // 添加props.saveLevel到依赖数组 const handleClickAnswer = () => { // 限制currentQuestion不超过题目数量-1 if (currentQuestion < quizList.length - 1) { setCurrentQuestion(prev => prev + 1); } }; if (isLoading) { return <div className="MainContainer">加载中...</div>; } if (error) { return <div className="MainContainer">错误:{error}</div>; } // 当quizList为空时显示提示 if (quizList.length === 0) { return <div className="MainContainer">暂无题目,请选择其他级别</div>; } const currentQuiz = quizList[currentQuestion]; return ( <div className="MainContainer"> <h4>Welcome to questionnaire</h4> <div> <h6>{currentQuiz.questionText}</h6> <div> {currentQuiz.answers.map((element, index) => ( <button key={index} onClick={handleClickAnswer}> {element.answerText} </button> ))} </div> </div> </div> ); } function mapStateToProps(state) { return { saveLevel: state.saveLevel }; } export default connect(mapStateToProps, null)(Questionnaire);
内容的提问来源于stack exchange,提问作者elodie rin
相关产品推荐
相关产品推荐

