如何使用 useEffect 挂钩定期获取请求?

How to fetch request in regular intervals using the useEffect hook?

我想做的是每 5 秒从一个随机引用 API 中获取一个随机引用,并将其内容设置为 React 组件。 我能够成功获取请求并显示其内容,但是在 运行 setInterval 方法与获取方法 fetchQuote 和 5 秒间隔之后,内容在该间隔内更新多次。

import { Badge, Box, Text, VStack, Container} from '@chakra-ui/react';
import React, { useState, useEffect } from 'react';
import axios from 'axios';


const  RandomQuotes = () => {
    const [quote, setQuote] = useState<Quote>(quoteObject);
    const [error, setError]: [string, (error: string) => void] = React.useState("");
    const [loading, setLoading] = useState(true);

    const fetchQuote = () => {
        axios.get<Quote>(randomQuoteURL)
            .then(response => {
                setLoading(false);
                setQuote(response.data);
            })
            .catch(ex => {
                setError(ex);
                console.log(ex)
            });
    }

    setInterval(() => setLoading(true), 5000);


    useEffect(fetchQuote, [loading, error]);

    const { id, content, author } = quote;

    return (
        <>
            <RandomQuote
                quoteID={id}
                quoteContent={content}
                quoteAuthor={author}
            />
        </>
    );

}

当任何状态或道具值更新时,您的函数体将 re-run,称为 re-render。

并且你已经在主函数中调用了 setInterval(!!!),所以每次组件 re-renders,它都会一次又一次地创建另一个间隔。您的浏览器将在几分钟后卡住。

你需要这个间隔定义一次,这就是useEffect第二个参数为空的目的。

此外,使用 loading 标志作为 API 调用的触发器是可行的,但在语义上没有任何意义,而且观察者非常昂贵且不需要。

这是一个大致正确的例子:

useEffect(() => {
  const myInterval = setInterval(fetchQuote, 5000);

  return () => {
    // should clear the interval when the component unmounts
    clearInterval(myInterval);
  };
}, []);

const fetchQuote = () => {
  setLoading(true);
  
  // your current code
};