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

React中渲染展示多组对象数组的正确方式及最佳实践

最佳实现:React中从REST API获取多数组数据并展示

首先得纠正一个误区:你绝对不能在Render阶段发起网络请求。Render方法的设计是纯函数——它只负责根据当前的state和props输出UI,不能包含任何副作用(比如网络请求、修改DOM、设置定时器等)。如果在Render里发请求,会导致每次组件渲染都触发请求,进而引发无限循环,完全不符合React的设计规范。所以你最初用componentDidMount(或者函数式组件里的useEffect)来发起请求的思路是完全正确的,不需要改到Render里。

接下来针对你的场景,我来给出最佳实现方案,分类组件和现在更推荐的函数式组件两种情况:


一、类组件优化方案

你的第二个componentDidMount写法是对的——把API返回的整个对象(包含home和about数组)存在state里,而不是只存data.home。我们还需要补充加载状态、错误处理,以及更健壮的渲染逻辑:

import React, { Component } from 'react';
import { render } from 'react-dom';
import './style.css';

class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'React',
      // 初始化更明确的结构,避免渲染时出现undefined报错
      awsApiData: { home: [], about: [] },
      isLoading: true, // 标记数据是否正在加载
      error: null // 存储请求错误信息
    };
  }

  componentDidMount() {
    console.log('app mounted');
    fetch('https://onelbip0e6.execute-api.eu-west-2.amazonaws.com/livestage/data')
      .then(response => {
        // 手动检查HTTP响应状态,fetch不会自动处理4xx/5xx错误
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
      })
      .then(data => {
        this.setState({
          awsApiData: data,
          isLoading: false
        });
        console.log(data);
      })
      .catch(error => {
        this.setState({
          error: error.message,
          isLoading: false
        });
        console.error('请求失败:', error);
      });
  }

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

    // 加载中状态:给用户明确的反馈
    if (isLoading) {
      return <div>加载中...</div>;
    }

    // 错误状态:友好提示错误信息
    if (error) {
      return <div>请求出错:{error}</div>;
    }

    // 正常渲染数据:分别处理home和about数组
    return (
      <div className="app-container">
        <h2>首页内容</h2>
        {awsApiData.home.map((item, index) => (
          // 给每个列表项加唯一key,帮助React优化渲染性能
          <div key={index} className="content-card">
            <h3>{item.title}</h3>
            <p>{item.body}</p>
            {/* 只在有图片链接时渲染图片,避免无效请求 */}
            {item.image && <img src={item.image} alt={item.title} className="content-image" />}
          </div>
        ))}

        <hr />

        <h2>关于我们</h2>
        {awsApiData.about.map((item, index) => (
          <div key={index} className="content-card">
            <h3>{item.title}</h3>
            <p>{item.body}</p>
            {item.image && <img src={item.image} alt={item.title} className="content-image" />}
          </div>
        ))}
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

二、函数式组件推荐方案

现在React官方更推荐使用函数式组件+Hooks的写法,代码更简洁,逻辑更清晰:

import React, { useState, useEffect } from 'react';
import { render } from 'react-dom';
import './style.css';

const App = () => {
  const [name, setName] = useState('React');
  // 初始化状态,和类组件保持一致
  const [awsApiData, setAwsApiData] = useState({ home: [], about: [] });
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  // useEffect替代componentDidMount,空依赖数组表示只在组件挂载时执行一次
  useEffect(() => {
    console.log('app mounted');
    // 用async/await让异步代码更易读
    const fetchApiData = async () => {
      try {
        const response = await fetch('https://onelbip0e6.execute-api.eu-west-2.amazonaws.com/livestage/data');
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        setAwsApiData(data);
        setIsLoading(false);
        console.log(data);
      } catch (err) {
        setError(err.message);
        setIsLoading(false);
        console.error('请求失败:', err);
      }
    };

    fetchApiData();
  }, []);

  // 加载和错误状态处理
  if (isLoading) return <div>加载中...</div>;
  if (error) return <div>请求出错:{error}</div>;

  // 渲染数据
  return (
    <div className="app-container">
      <h2>首页内容</h2>
      {awsApiData.home.map((item, idx) => (
        <div key={idx} className="content-card">
          <h3>{item.title}</h3>
          <p>{item.body}</p>
          {item.image && <img src={item.image} alt={item.title} className="content-image" />}
        </div>
      ))}

      <hr />

      <h2>关于我们</h2>
      {awsApiData.about.map((item, idx) => (
        <div key={idx} className="content-card">
          <h3>{item.title}</h3>
          <p>{item.body}</p>
          {item.image && <img src={item.image} alt={item.title} className="content-image" />}
        </div>
      ))}
    </div>
  );
};

render(<App />, document.getElementById('root'));

关键注意点总结

  1. 永远不要在Render里发请求:Render是纯函数,副作用会导致无限循环和性能问题。
  2. 处理加载/错误状态:避免用户看到空白页面或者控制台报错,提升体验。
  3. HTTP错误处理:fetch不会自动捕获4xx/5xx错误,必须手动检查response.ok。
  4. 唯一key的使用:如果API返回每个item的唯一ID(比如id: 1),尽量用ID作为key,而不是index,这样React的列表渲染性能更好。
  5. 条件渲染图片:只在item.image存在时渲染图片,避免无效的图片请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 21:37:49