UseEffect 中的 SetInterval 无延迟

时间:2021-05-15 16:15:40

标签: javascript reactjs react-hooks setinterval use-effect

我正在用 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引起)。

所以我的问题是,是否有任何解决方案可以获得相同的行为,而无需在开始时延迟?

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

谢谢!

2 个答案:

答案 0 :(得分:2)

定义间隔时只调用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]);

答案 1 :(得分:0)

是的,我已经尝试过这个解决方案,首先调用函数然后设置一个间隔。 但结果是横幅开始出现疯狂的行为。它在一秒钟内无休止地变化 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>
  );
};

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