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

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是空数组,无法生成有效随机索引;异步加载完成后状态更新,但没有自动执行选名言的操作。以下是两种可行方案:

方案一:监听名言数据变化,自动触发选择

  1. 修复handleNewQuote的依赖问题,用useCallback包裹并添加正确依赖:
const handleNewQuote = useCallback(() => {
    const randomIndex = Math.floor(Math.random() * quotes.length);
    setRandomQuote(quotes[randomIndex]);
}, [quotes]);
  1. 新增一个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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 00:36:21