React开发中如何从API返回的数组中仅渲染单条/第一条数据
随机名言功能修复方案
问题根源
你原代码的核心问题是对全量名言数组执行map生成了所有名言的JSX节点,一次性渲染导致内存占用过高崩溃,同时异步逻辑顺序错误导致无法生成有效随机下标:
- 调用
arrayOfQuotes.map会遍历接口返回的1600+条名言全部生成DOM节点,直接存入状态后渲染必然触发内存溢出 - 异步请求
QuoteAPI还没执行完毕时,setIndex(randomIndex(quote))就已经触发,此时quote还是初始空值,无法计算出有效随机下标 - 不需要把JSX节点存入状态,直接存储原始名言数组即可,渲染时按需取单条数据生成节点更合理
修正后完整代码
import { useState, useEffect } from 'react'; import axios from 'axios'; // 生成有效随机下标 const randomIndex = (arr) => { if (!arr || !arr.length) return 0; return Math.floor(Math.random() * arr.length); }; const QuoteCard = () => { // 存储全量名言原始数组 const [quotesArray, setQuotesArray] = useState([]); // 存储当前展示的名言下标 const [currentIndex, setCurrentIndex] = useState(0); // 拉取全量名言数组 const fetchQuotes = async () => { try { const { data } = await axios.get("https://type.fit/api/quotes"); setQuotesArray(data); // 拿到数组后生成第一个随机下标 setCurrentIndex(randomIndex(data)); } catch (err) { console.error('名言加载失败', err); } }; // 页面初始化仅调用一次接口 useEffect(() => { fetchQuotes(); }, []); // 加载兜底 if (!quotesArray.length) return <div>加载中...</div>; // 仅取出当前要展示的单条名言 const currentQuote = quotesArray[currentIndex]; return ( <div key={currentQuote.id}> <h3>{currentQuote.text}</h3> <p>{currentQuote.author || '佚名'}</p> {/* 可选:新增切换随机名言的按钮 */} <button onClick={() => setCurrentIndex(randomIndex(quotesArray))}> 切换名言 </button> </div> ); }; export default QuoteCard;
核心改动说明
- 调整状态逻辑:只存储原始名言数组,不提前生成全量JSX节点,大幅降低内存占用
- 修正异步顺序:接口返回全量数组后再生成随机下标,避免空值计算报错
- 优化渲染逻辑:无需调用
map遍历全量数组,直接取下标对应的单条数据渲染即可 - 补充边界处理:新增加载状态、作者为空时的兜底显示,避免渲染异常
如果你确实需要用
map仅渲染第一条数据的特殊场景,可以截取数组第一项后再遍历:arrayOfQuotes.slice(0,1).map(item => /* 渲染逻辑 */),但该场景下直接取单条数据渲染性能更优,无需使用map。
内容的提问来源于stack exchange,提问作者Bombard
相关产品推荐
相关产品推荐

