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

React使用Fetch从指定API获取对象数组报错,寻求解决方案

解决React Fetch API时“无法获取undefined的值”的问题

问题分析

你遇到的错误核心原因有两个:

  1. 初始状态与API返回结构不匹配:你初始化的state.books是一个空数组,但目标API返回的是一个包含results数组的对象(类似{ count: xxx, results: [{}, {}, ...] })。
  2. 异步请求的时序问题:组件第一次渲染时,componentDidMount里的fetch请求还没完成,此时this.state.books还是初始的空数组,你尝试访问this.state.books.results——数组根本没有results属性,自然会抛出“无法获取undefined的值”的错误。

解决方案一:直接存储需要的数组(推荐)

调整state的赋值逻辑,把API返回的data.results直接存入state.books,这样books始终是数组,既符合你的使用习惯,也避免了多余的属性访问:

import React, { Component } from 'react';
class App extends Component {
  constructor() {
    super()
    // 初始状态保持books为数组,和最终要渲染的数据结构一致
    this.state = { books: [] }
  }

  componentDidMount() {
    fetch('http://skunkworks.ignitesol.com:8000/books/')
      .then(res => res.json())
      .then(data => {
        // 直接把API返回的results数组赋值给state.books
        this.setState({ books: data.results })
      })
      .catch(e => { console.log('请求出错:', e); });
  }

  render() {
    // 现在books就是数组,直接遍历即可,初始空数组也不会报错
    const bookList = this.state.books.map(book => (
      <div key={book.id} style={{ margin: '10px 0' }}>
        <h3>{book.title}</h3>
        <p>作者:{book.authors.join(', ')}</p>
        <p>出版年份:{book.published_date}</p>
      </div>
    ))

    return (
      <div style={{ padding: '20px' }}>
        <h1>Books</h1>
        {bookList}
      </div>
    )
  }
}
export default App;

解决方案二:添加空值判断(兼容现有结构)

如果你想保持state的结构不变,可以在访问results前做空值校验,或者使用ES6的可选链操作符?.来避免报错:

render() {
  // 用可选链判断,如果books不存在或没有results属性,就返回空数组
  const bookList = (this.state.books?.results || []).map(book => (
    <div key={book.id}>
      <h3>{book.title}</h3>
      <p>作者:{book.authors.join(', ')}</p>
    </div>
  ))

  return (
    <div>
      <h1>Books</h1>
      {bookList}
    </div>
  )
}

进阶优化:添加加载和错误状态

为了提升用户体验,建议在异步请求过程中加入加载提示和错误处理:

import React, { Component } from 'react';
class App extends Component {
  constructor() {
    super()
    this.state = { 
      books: [], 
      isLoading: true, // 加载状态
      error: null      // 错误信息
    }
  }

  componentDidMount() {
    fetch('http://skunkworks.ignitesol.com:8000/books/')
      .then(res => {
        // 先判断请求是否成功
        if (!res.ok) throw new Error('请求失败,请稍后重试')
        return res.json()
      })
      .then(data => {
        this.setState({ books: data.results, isLoading: false })
      })
      .catch(e => { 
        this.setState({ error: e.message, isLoading: false })
        console.log(e); 
      });
  }

  render() {
    const { books, isLoading, error } = this.state;

    // 加载中状态
    if (isLoading) return <div style={{ padding: '20px' }}>正在加载书籍...</div>;
    // 错误状态
    if (error) return <div style={{ padding: '20px', color: 'red' }}>出错了:{error}</div>;

    const bookList = books.map(book => (
      <div key={book.id} style={{ margin: '10px 0' }}>
        <h3>{book.title}</h3>
        <p>作者:{book.authors.join(', ')}</p>
        <p>出版年份:{book.published_date}</p>
      </div>
    ))

    return (
      <div style={{ padding: '20px' }}>
        <h1>Books</h1>
        {bookList}
      </div>
    )
  }
}
export default App;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:34:01