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

React组件中Promise结果存入数组后渲染为空,如何不异步化组件解决?

问题:异步请求获取数据后数组为空,无法渲染书籍列表

以下是我编写的React组件代码,调用异步函数获取指定分类的书籍:

function Bookshelf(props) {
  const { genre } = props;

  const books = [];

  const arrayOfPromises = [];

  arrayOfPromises.push(getBooksUnderGenre(genre)) // 这是异步函数
  Promise.all(arrayOfPromises)
    .then(results => {
        console.log(results);
        const result = results[0];
        books.push(result);
    });

  books.map((book, i) => {
    return (
        <Text> {book.name} </Text>
    )
  });
};

执行console.log(results)时终端能正常输出所需结果,但const books = []始终是空数组,导致map操作在空数组上执行,没有渲染任何内容。想问下能不能在不把Bookshelf组件改成异步函数的前提下解决这个问题?如果不行的话,正确的做法是什么?

附results的输出内容:

[
  [
    {
      genre: "fantasy",
      id: "19",
      type: "book",
      name: "Star Night",
    },
    {
      genre: "fantasy",
      id: "20",
      type: "book",
      name: "A Moon Far Away",
    },
    {
      genre: "fantasy",
      id: "21",
      type: "book",
      name: "Green Lands",
    },
  ],
];

解决方案

首先明确:React组件不能是异步函数,因为React要求组件返回JSX元素,而异步函数返回的是Promise,React无法识别,所以不存在把组件改成异步的说法。你的核心问题有两个:

  1. 异步操作滞后于组件渲染,当执行books.map时,Promise还未完成,books还是初始的空数组
  2. 直接修改普通数组books不会触发React组件的重新渲染,就算后续异步请求完成、数组内容更新了,组件也不会重新读取新内容

正确的解决方式是用React的状态管理和副作用处理:

修改后的代码

import { useState, useEffect } from 'react';

function Bookshelf(props) {
  const { genre } = props;
  // 用useState保存书籍状态,初始为空数组
  const [books, setBooks] = useState([]);

  // 用useEffect处理异步请求,依赖genre,当genre变化时重新请求
  useEffect(() => {
    // 定义异步函数处理请求
    const fetchBooks = async () => {
      try {
        const results = await Promise.all([getBooksUnderGenre(genre)]);
        // results是数组的数组,取出里面的书籍列表
        const bookList = results[0];
        // 更新状态,触发组件重新渲染
        setBooks(bookList);
      } catch (err) {
        // 处理请求错误
        console.error('获取书籍失败:', err);
      }
    };

    fetchBooks();
  }, [genre]); // 依赖项:genre变化时重新执行

  // 渲染书籍列表,空数组时显示加载提示
  return (
    <>
      {books.length === 0 ? (
        <Text>加载中...</Text>
      ) : (
        books.map((book) => (
          <Text key={book.id}> {book.name} </Text>
        ))
      )}
    </>
  );
};

关键说明

  • useState:用来保存书籍数据,状态更新时会自动触发组件重新渲染,异步请求完成后更新状态,组件就能拿到最新的书籍列表并渲染
  • useEffect:专门处理组件的副作用(比如异步请求),第二个参数是依赖数组,只有当genre变化时才会重新发起请求,避免不必要的重复请求
  • 异步处理:用async/await替代then写法,代码更清晰;同时加上错误捕获,避免请求失败导致的问题
  • key属性:map渲染列表时必须加唯一的key,这里用书籍的id,符合React的性能优化要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 12:30:45