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

React中map处理Hook数组渲染时出现TypeError问题求助

问题分析与解决方案

错误原因

你遇到的Uncaught TypeError: Cannot read properties of undefined (reading 'value'),核心原因是数组结构处理错误:

  • 你创建的answer数组通过answer.push(questions, answers)后,实际结构是[问题对象, 答案数组],而非包含questions和answers属性的对象数组。
  • 后续answer.map(({questions, answers}) => ...)尝试解构每个数组元素的questions属性,但数组里的第一个元素是问题对象本身,第二个是答案数组,两者都没有questions属性,因此questions为undefined,访问questions.value就会触发错误。

此外还有两个次要问题:

  • 使用slice获取错误答案时,slice返回的是数组(比如incorrect_answers.slice(0,1)得到["xxx"]),而非字符串,导致答案按钮显示数组而非文本。
  • 冗余的嵌套map,每个题目只需要渲染一次问题和对应的一组答案,不需要再遍历answer数组。

修正后的代码

import { useState, useEffect } from 'react'
import { nanoid } from 'nanoid'
import './App.css'
import FirstPage from './components/FirstPage'
import Quiz from './components/Quiz'

function App() {
  const [startGame, setStartGame] = useState(false)
  const [quizData, setQuizData] = useState([])

  useEffect(() => {
    fetch(`https://opentdb.com/api.php?amount=5`)
      .then(res => res.json())
      .then(data => setQuizData(data.results))
  }, [])

  function gameStart() {
    setStartGame(true)
  }

  const displayQuestions = quizData.map(({ question, correct_answer, incorrect_answers }) => {
    // 修正:直接取字符串而非数组,用下标获取错误答案文本
    const answer1 = {
      text: incorrect_answers[0],
      is_selected: false,
      is_correct: false,
      id: nanoid()
    }

    const answer2 = {
      text: incorrect_answers[1],
      is_selected: false,
      is_correct: false,
      id: nanoid()
    }

    const answer3 = {
      text: correct_answer,
      is_selected: false,
      is_correct: true,
      id: nanoid()
    }

    const answer4 = {
      text: incorrect_answers[2],
      is_selected: false,
      is_correct: false,
      id: nanoid()
    }

    // 合并所有答案并打乱顺序(可选,让正确答案位置随机)
    const answers = [answer1, answer2, answer3, answer4].sort(() => Math.random() - 0.5)
    const questionObj = {
      value: question,
      id: nanoid()
    }

    // 修正:直接渲染单个问题和对应的答案列表,不需要嵌套map
    return (
      <div key={questionObj.id}>
        <ul>
          <li className='questions'>{questionObj.value}</li>
          {answers.map(answer => (
            <button key={answer.id} className='answers'>
              {answer.text}
            </button>
          ))}
        </ul>
      </div>
    )
  })

  return (
    <>
      <h1 className='bloc'></h1>
      <h1 className='bloc2'></h1>
      {startGame ? <Quiz displayQuestions={displayQuestions} /> : <FirstPage gameStart={gameStart} />}
    </>
  )
}

export default App

关键修正点

  • 数组结构调整:不再将问题和答案塞进同一个数组,而是直接为每个题目创建独立的问题对象和答案数组,直接渲染,避免错误的解构操作。
  • 修正答案文本获取:用数组下标incorrect_answers[0]代替slice,直接获取字符串类型的答案文本。
  • 可选优化:添加sort(() => Math.random() - 0.5)打乱答案顺序,让Quiz更符合实际使用场景。
  • 移除冗余嵌套map:每个题目对应唯一的问题和答案组,直接渲染即可,无需额外遍历。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:01:01