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

React JS中MongoDB数据获取完成前的渲染错误修复:Quiz应用MCQ选项无法读取问题

解决Quiz应用中MCQ数据加载时的Undefined错误

我来帮你搞定这个问题——你遇到的是典型的React异步数据加载时序冲突:组件刚初始化时,MCQ请求依赖的requestedQuestion还没拿到有效数据(因为quizInfo还在从接口加载),导致发起了一次无效请求,进而让mcqInfo处于未就绪状态,这时候访问它的属性就会抛出Cannot read properties of undefined错误。咱们一步步拆解问题,然后给出解决方案:

问题根源拆解

  1. 组件初始化时,quizInfo的初始状态里q_questions是空数组,所以requestedQuestion = quizQuestions[currentQuestion]等于undefined,这时候MCQ的useEffect会执行,用undefined作为ID去请求数据,要么返回无效结果,要么直接报错,导致mcqInfo变成错误状态(比如undefined)。
  2. 当quizInfo加载完成后,quizQuestions更新,requestedQuestion变成有效的问题ID,MCQ的useEffect再次执行,这时候才会拿到正确的MCQ数据。
  3. 在这两次请求之间,你尝试访问mcqInfo.m_alternatives,但此时mcqInfo要么是初始空状态,要么是错误的undefined,自然会触发报错。

解决方案:控制加载时序+空值保护

下面是修改后的完整代码,我会标注每一处关键修改的原因:

import React, { useEffect, useState } from "react";
import shuffleMcq from "../components/shuffleMcq";

const QuizTakePage = ({ match }) => {
  const reqUrl = match.params.path; // 获取URL中的Quiz ID
  const [quizInfo, setQuizInfo] = useState({
    q_title: "",
    q_seo_description: "",
    q_questions: [],
    q_tags: [],
    m_subject: "",
  });
  // 新增:标记Quiz数据是否加载完成
  const [isQuizLoaded, setIsQuizLoaded] = useState(false);

  useEffect(() => {
    const fetchQuizData = async () => {
      try {
        const reqApiUrl = '/quiz/api/qid/' + reqUrl;
        const fetchedApiResult = await fetch(reqApiUrl);
        const resultJson = await fetchedApiResult.json();
        setQuizInfo(resultJson);
        setIsQuizLoaded(true); // Quiz数据加载完成后标记状态
      } catch (error) {
        console.error("加载Quiz数据失败:", error);
      }
    };
    fetchQuizData();
  }, [reqUrl]); // 依赖reqUrl,确保URL变化时重新请求Quiz数据

  // Quiz数据提取
  const quizTitle = quizInfo.q_title;
  const quizDesc = quizInfo.q_seo_description;
  const quizQuestions = quizInfo.q_questions;

  // MCQ相关状态
  const [currentQuestion, setCurrentQuestion] = useState(0);
  const [mcqInfo, setMcqInfo] = useState({
    m_title: "",
    m_question: "",
    m_alternatives: [],
    m_language: "",
  });
  // 新增:标记MCQ数据是否加载完成
  const [isMcqLoaded, setIsMcqLoaded] = useState(false);

  useEffect(() => {
    // 新增:只有当Quiz加载完成,且当前问题ID有效时,才发起MCQ请求
    if (!isQuizLoaded || !quizQuestions[currentQuestion]) return;

    const fetchApiResponse = async () => {
      try {
        setIsMcqLoaded(false); // 开始加载MCQ前标记状态
        const requestedQuestion = quizQuestions[currentQuestion];
        const reqApiUrl = '/mcq/api/mid/' + requestedQuestion;
        const fetchedApiResult = await fetch(reqApiUrl);
        const resultJson = await fetchedApiResult.json();
        setMcqInfo(resultJson);
        setIsMcqLoaded(true); // MCQ加载完成后标记状态
      } catch (error) {
        console.error("加载MCQ数据失败:", error);
        setIsMcqLoaded(true); // 即使请求失败,也标记加载完成避免无限循环
      }
    };
    fetchApiResponse();
  }, [isQuizLoaded, currentQuestion, quizQuestions]); // 依赖关键状态,确保数据变化时重新请求

  // 新增:空值保护,用可选链避免访问undefined的属性
  const mcqQuestion = mcqInfo?.m_question || "加载中...";
  const mcqOptions = mcqInfo?.m_alternatives || [];

  console.log(mcqOptions);

  return (
    <>
      {/* 新增:Quiz加载中显示提示 */}
      {!isQuizLoaded ? (
        <div>加载Quiz信息中...</div>
      ) : (
        <>
          <h1>{quizTitle}</h1>
          <p>{quizDesc}</p>
          {/* 新增:MCQ加载中显示提示 */}
          {!isMcqLoaded ? (
            <div>加载题目中...</div>
          ) : (
            <div>
              <h3>{mcqQuestion}</h3>
              <ul>
                {mcqOptions.map((option, index) => (
                  <li key={index}>{option}</li>
                ))}
              </ul>
            </div>
          )}
        </>
      )}
    </>
  );
};

export default QuizTakePage;

关键修改说明

  1. 加载状态标记:isQuizLoaded和isMcqLoaded用来明确数据的加载状态,在加载过程中给用户显示友好提示,避免渲染未就绪的内容。
  2. 请求时机控制:MCQ的useEffect里增加了判断,只有当Quiz数据加载完成且当前问题ID有效时,才发起MCQ请求,彻底避免用undefined作为ID的无效请求。
  3. 空值保护:使用可选链操作符?.(比如mcqInfo?.m_alternatives),即使mcqInfo是undefined也不会报错,再通过||设置默认值,保证代码的健壮性。
  4. 错误处理:给fetch添加try/catch,捕获请求过程中的错误,避免组件崩溃,同时方便调试问题。
  5. 依赖项优化:把reqUrl加入Quiz请求的依赖项,确保URL变化时重新请求;MCQ请求的依赖项包含所有影响请求结果的状态,确保数据更新时能同步发起新请求。

这样修改后,不仅能解决你遇到的undefined错误,还能给用户提供更流畅的加载体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 21:09:07