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

React中API请求等待时渲染多个加载提示的实现方法

解决React多名言加载提示的问题

问题根源

你当前的代码逻辑是等API返回名言数据后,才把数据添加到quotes数组,所以QuoteItem组件从一开始拿到的就是完整的名言数据,根本没机会显示"Loading..."。要实现点击按钮先出加载框、再替换成名言的效果,得先把「加载状态的项」加到列表里,等请求完成后再更新这个项的内容。

具体修改方案

1. 修改QuotesLogic.jsx:区分加载/完成状态的列表项

给每个列表项增加状态标识,点击按钮时先插入一个「加载中」的项,请求完成后再替换成真实名言数据:

import React, { useState, useEffect } from 'react';
import QuoteList from './QuoteList';

// 生成唯一ID,避免用index当key的问题
const generateId = () => Math.random().toString(36).slice(2, 10);

export default function QuotesLogic() {
  const [quotes, setQuotes] = useState([]);

  useEffect(() => {
    fetchQuote();
  }, []);

  const fetchQuote = async () => {
    // 1. 先添加一个加载状态的项
    const loadingId = generateId();
    setQuotes(prev => [...prev, { id: loadingId, loading: true }]);

    try {
      // 2. 请求API
      const response = await fetch('https://api.quotable.io/random');
      const data = await response.json();
      await new Promise((resolve) => setTimeout(resolve, 1000)); // 测试用延迟

      // 3. 替换加载项为真实名言
      setQuotes(prev => prev.map(item => 
        item.id === loadingId ? { id: loadingId, loading: false, data } : item
      ));
    } catch (err) {
      // 处理请求失败的情况,比如替换成错误提示
      setQuotes(prev => prev.map(item => 
        item.id === loadingId ? { id: loadingId, loading: false, error: '加载失败' } : item
      ));
    }
  };

  return (
    <section>
      <button onClick={fetchQuote}>Generate new</button>
      <QuoteList quotes={quotes} />
    </section>
  );
}

2. 修改QuoteItem.jsx:根据传入的状态渲染内容

不再用组件内部的loading状态,直接读取父组件传入的列表项状态:

import React from 'react';

export default function QuoteItem({ item }) {
  if (item.loading) {
    return (
      <div className='border border-green-500'>
        <p>Loading...</p>
      </div>
    );
  }

  if (item.error) {
    return (
      <div className='border border-red-500'>
        <p>{item.error}</p>
      </div>
    );
  }

  const quote = item.data;
  return (
    <div className='border border-green-500'>
      <p>{quote.content}</p>
      <p className='text-right'>{quote.author}</p>
      <p>insert other quote attributes</p>
    </div>
  );
}

3. 调整QuoteList.jsx:传递正确的属性并使用唯一key

import React from 'react';
import QuoteItem from './QuoteItem';

export default function QuoteList({ quotes }) {
  return (
    <div>
      {quotes.map((item) => (
        <QuoteItem key={item.id} item={item} />
      ))}
    </div>
  );
}

效果说明

现在连续点击按钮时,每点击一次就会立刻添加一个显示"Loading..."的框,等API响应完成后,对应的加载框会自动替换成真实的名言内容。即使多次点击,每个加载状态的项都会独立等待自己的API请求完成,不会互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 21:05:45