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

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')

错误原因分析

  1. 初始状态访问undefined:组件初始化时quizList是空数组,quizList[0]为undefined,直接访问.questionText会触发类型错误。
  2. fetch语法错误:fetch调用末尾缺失闭合括号,会导致请求无法正常执行。
  3. useEffect依赖缺失:依赖数组为空,当props.saveLevel变化时不会重新触发API请求;若组件初始化时props.saveLevel未同步获取到,也会导致请求参数异常。

修复步骤

  1. 添加加载状态:在数据未返回时显示加载提示,避免访问未定义的属性。
  2. 修复fetch语法错误:补上fetch调用末尾的闭合括号。
  3. 完善useEffect依赖:将props.saveLevel加入依赖数组,确保级别变化时重新请求数据。
  4. 添加边界检查:确保currentQuestion不超出题目数量范围,避免切换题目时出现越界错误。
  5. 可选:添加错误处理:捕获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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:35:47