React Lifecycles managing intervals with changing values

Viewed 30

In one of my components I have a useEffect setup where an interval is set to fetch a function.

It's basically set up as follows:

...

const token = useToken() // custom hook that updates whenever access_token updates

const fetchData = useCallback(() => {
  callAPI(token)
}, [token])

useEffect(() => {
  if (!token) return

  fetchData()

  const interval = setInterval(fetchData, 60000)

  return () => {
    clearInterval(interval)
  }
}, [token]}

...

It is supposed fetchData every 60 seconds which it does.

What it also needs to do (which it doesn't) is whenever the token is updated, it should account for that.

What I've currently done to try solve that is clear the interval when the token changes and start the process over. But I think I've handled that incorrectly in my attempts above.

Any idea on how to accomplish this correctly?

1 Answers

the only thing missing is fetchData should be added to the dependency array to make sure that the useEffect uses the updated callback

useEffect(() => {
    if (!token) return

    fetchData()

    const interval = setInterval(fetchData, 60000)

    return () => {
        clearInterval(interval)
    }
}, [token, fetchData])

but you can also move the fetchData(this time fetchData doesn't have to be memorized with useCallback) function inside the useEffect, that way you can only have token as a dependency:

useEffect(() => {
    const fetchData = () => {
        if(!token) return;

        callAPI(token)
    };

    fetchData();
    const interval = setInterval(fetchData, 60000)

    return () => {
        clearInterval(interval)
    }
}, [token])

Edit: You can remove token form the useEffect this way:

const fetchData = useCallback(() => {
    if(!token) return; // moved the token check here
    
    callAPI(token)
  }, [token])
  
useEffect(() => {
    fetchData();
    const interval = setInterval(fetchData, 60000)

    return () => {
        clearInterval(interval)
    }
}, [fetchData])
Related