简体   繁体   中英

SetInterval in UseEffect without Delay

I am building a movie app in React to practice.

In the homepage there is a big banner with movie poster and information about movies, content of this banner is changing every 5 seconds. I created this function for this:

 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]);

This solution has a problem: there is a 5sec delay when I run this app for the first time (caused by setInterval).

So my question is, if there is any solution to get the same behaviour, just without the delay at the start?

I tried a lot of different solutions including defining new states, but all of them causes bugs or infinite loop.

Thanks!

Just call fetchData when defining the interval?

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]);

Yes, I have already tried exactly this solution with invoking function firstly and then setting an interval. But the result is that banner starts to have crazy behaviour. It changes literally 10x in a single second endlessly.

I attach a whole updated component code to be sure I didn't miss something to send:

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>
  );
};

Any ideas what should caused it/how to prevent from this behaviour?

I fixed the issue, after adding another useEffect hook. But i am not sure if it will call some other issue.

useEffect(() => { 
  fetchData()
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM