UseEffect 中的 SetInterval 无延迟

Posted

技术标签:

【中文标题】UseEffect 中的 SetInterval 无延迟【英文标题】:SetInterval in UseEffect without Delay 【发布时间】:2021-08-05 11:37:16 【问题描述】:

我正在用 React 构建一个电影应用来练习。

首页有一个大横幅,上面有电影海报和电影信息,这个横幅的内容每5秒变化一次。我为此创建了这个函数:

 const [movie, setMovie] = useState('');     //const movie returns object of one random movie

  useEffect(() => 
    async function fetchData() 
      const request = await axios.get(requests.fetchNetflixOriginals);  
      setMovie(
        request.data.results[
          Math.floor(Math.random() * request.data.results.length)
        ]
      );
    
    const interval = setInterval(() => 
      fetchData();
    , 5000)
   return () => clearInterval(interval)   
  , [movie]);

这个解决方案有一个问题:我第一次运行这个应用程序有5秒的延迟(由setInterval引起)。

所以我的问题是,是否有任何解决方案可以得到相同的行为,而且一开始就没有延迟?

我尝试了很多不同的解决方案,包括定义新状态,但所有这些都会导致错误或无限循环。

谢谢!

【问题讨论】:

【参考方案1】:

定义区间时只需调用fetchData

useEffect(() => 
    async function fetchData() 
        const request = await axios.get(requests.fetchNetflixOriginals);
        setMovie(
            request.data.results[
            Math.floor(Math.random() * request.data.results.length)
            ]
        );
    
    fetchData();
    const interval = setInterval(fetchData, 5000)
    return () => clearInterval(interval)
, [movie]);

【讨论】:

【参考方案2】:

是的,我已经尝试过这个解决方案,首先调用函数,然后设置一个时间间隔。 但结果是横幅开始有疯狂的行为。它在一秒钟内不断变化 10 倍。

我附上了一个完整的更新组件代码,以确保我没有错过要发送的内容:

const Banner = () => 
  const [movie, setMovie] = useState();

  useEffect(() => 
    async function fetchData() 
        const request = await axios.get(requests.fetchNetflixOriginals);
        setMovie(
            request.data.results[
            Math.floor(Math.random() * request.data.results.length)
            ]
        );
    
    fetchData();
    const interval = setInterval(fetchData, 5000)
    return () => 
      clearInterval(interval)
    
, [movie]);

  function truncate(str, n) 
    return str?.length > n ? str.substr(0, n - 1) + '...' : str;
  

  return (
    <header
      className='banner'
      style=
        backgroundSize: 'cover',
        backgroundImage: `url(https://image.tmdb.org/t/p/original/$movie?.backdrop_path)`, 
        backgroundPosition: 'center center',
      
    >
      <div className='banner__contents'>
        <h1 className='banner__title'>
          movie?.title || movie?.name || movie?.original_name
        </h1>
        <div className='banner__buttons'>
          <button className='banner__button'>Play</button>
          <button className='banner__button'>My List</button>
        </div>
        <h1 className='banner__description'>
          truncate(movie?.overview, 120)
        </h1>
      </div>
      <div className='banner--fadeBottom'></div>
    </header>
  );
;

任何想法应该导致它/如何防止这种行为?

【讨论】:

【参考方案3】:

我在添加另一个 useEffect 挂钩后解决了这个问题。但我不确定它是否会调用其他问题。

useEffect(() =>  
  fetchData()
)

【讨论】:

以上是关于UseEffect 中的 SetInterval 无延迟的主要内容,如果未能解决你的问题,请参考以下文章

使用 useEffect 和 setInterval 一个接一个地打印一个字母

ReactJS 在 UseEffect 中使用 SetInterval 导致状态丢失

NextJs:在 React useEffect Hook 内使用变量调用 setInterval

React Jest setInterval 测试覆盖率

如何在反应中使用 setInterval?

使用 useEffect 和 jest.useFakeTimers() 进行测试