ReactJS随机名言生成器页面加载时不显示名言问题求助
问题:页面刷新后随机名言生成器不自动显示名言
我正在开发一个随机名言生成器,功能运行正常,但页面刷新时不会显示名言,必须点击“New Quote”按钮才能获取新名言。我希望DOM加载完成后就能自动显示名言。
我理解的问题是:useEffect调用fetchQuotes()的时机晚于handleNewQuote(),导致没有名言可加载。
我的代码
import { useCallback, useEffect, useState } from 'react'; import './App.css'; function App() { const quotesURL ='https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json'; const [quotes, setQuotes] = useState([]); const [randomQuote, setRandomQuote] = useState(''); const fetchQuotes = useCallback(() => { fetch(quotesURL) .then(response => response.json()) .then(data => setQuotes(data.quotes)) .catch(err => console.error(err)); // console.log(quotes); }, [quotesURL]); // eslint-disable-next-line react-hooks/exhaustive-deps const handleNewQuote = () => { const randomIndex = Math.floor(Math.random() * quotes.length); setRandomQuote(quotes[randomIndex]); }; useEffect(() => { fetchQuotes(); }, []); return ( <div> <div id='quote-box'> <div id='text'>{randomQuote.quote}</div> <div id='author'>{randomQuote.author}</div> <button id='new-quote' onClick={handleNewQuote}> New Quote </button> <a href='https://www.twitter.com/intent/tweet' id='tweet-quote'> Tweet Quote </a> </div> {quotes?.map((quote, index) => ( <div key={index}>{JSON.stringify(quote)}</div> ))} </div> ); } export default App;
解决方法
核心问题是获取到名言数据后,没有自动触发随机名言的选择逻辑:初始时quotes是空数组,无法生成有效随机索引;异步加载完成后状态更新,但没有自动执行选名言的操作。以下是两种可行方案:
方案一:监听名言数据变化,自动触发选择
- 修复
handleNewQuote的依赖问题,用useCallback包裹并添加正确依赖:
const handleNewQuote = useCallback(() => { const randomIndex = Math.floor(Math.random() * quotes.length); setRandomQuote(quotes[randomIndex]); }, [quotes]);
- 新增一个
useEffect,监听quotes状态,当数据加载完成后自动调用handleNewQuote:
useEffect(() => { if (quotes.length > 0) { handleNewQuote(); } }, [quotes, handleNewQuote]);
方案二:在数据获取成功后直接设置随机名言
修改fetchQuotes函数,拿到数据后直接生成随机名言并更新状态:
const fetchQuotes = useCallback(() => { fetch(quotesURL) .then(response => response.json()) .then(data => { const quoteList = data.quotes; setQuotes(quoteList); // 直接选择随机名言 const randomIndex = Math.floor(Math.random() * quoteList.length); setRandomQuote(quoteList[randomIndex]); }) .catch(err => console.error(err)); }, [quotesURL]);
额外优化:避免初始渲染报错
初始randomQuote是空字符串,直接访问randomQuote.quote会引发错误,建议将初始状态改为空对象:
const [randomQuote, setRandomQuote] = useState({});
或者在渲染时使用可选链:
<div id='text'>{randomQuote?.quote}</div> <div id='author'>{randomQuote?.author}</div>
内容的提问来源于stack exchange,提问作者Ali Bin Naseer
相关产品推荐
相关产品推荐

