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

React中访问state存储的对象数组属性报错如何解决?

问题根因
  • 组件首次渲染时,useEffect内的fetch异步请求还未返回,此时request状态是初始值空数组[],访问request[0]得到undefined,再读取undefined的属性就会直接抛出运行时错误。等请求完成、状态更新触发重渲染后,你才能正常拿到数组里的对象数据。
  • 代码第三行打印存在拼写错误:将request错写为requst,即使数据加载完成,该行也会触发变量未定义的错误。
修复方案

方案1:增加加载状态(推荐)

在请求完成前不渲染依赖接口数据的内容,从根源避免访问空值的问题,同时优化用户体验:

import React from 'react'

function QuizApp() {
  const [request, setRequest] = React.useState([])
  const [isLoading, setIsLoading] = React.useState(true)

  React.useEffect(() => {
    fetch('https://opentdb.com/api.php?amount=5')
      .then(res => res.json())
      .then(data => {
        const formattedData = data.results.map(({ question, correct_answer, incorrect_answers }) => ({
          question,
          correct_answer,
          incorrect_answers
        }))
        setRequest(formattedData)
        setIsLoading(false)
      })
      .catch(err => {
        console.error('题目获取失败:', err)
        setIsLoading(false)
      })
  }, [])

  // 加载阶段返回占位内容
  if (isLoading) {
    return <div>题目加载中,请稍候...</div>
  }

  // 到这里数据已经完成赋值,可以安全访问属性
  console.log(request[0])
  console.log(request[0]["question"])
  console.log(request[0].question)

  return (
    <div className="quiz-wrap">
      {request.map((quiz, idx) => (
        <div key={idx} className="quiz-item">
          {/* 接口返回的question带HTML转义字符,用以下方式正常渲染 */}
          <h3 dangerouslySetInnerHTML={{ __html: quiz.question }} />
          {/* 后续渲染正确答案、错误选项的逻辑 */}
        </div>
      ))}
    </div>
  )
}

export default QuizApp

方案2:可选链防御性访问

如果不想单独维护加载状态,可以用ES2020的可选链操作符?.做安全访问,当访问路径上出现null/undefined时会直接返回undefined,不会抛出错误:

// 首次渲染打印undefined,数据加载后打印对应问题内容,全程不会报错
console.log(request?.[0]?.question)

注意:opentdb接口返回的题目、答案字段包含HTML实体字符,直接作为文本渲染会出现&quot;这类转义内容,需要做转义处理后再展示,示例中使用的dangerouslySetInnerHTML是最简单的处理方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:57:11