DEV Community

Discussion on: React Hooks Series: useRef

Collapse
icyjoseph profile image
Joseph • Edited on

This was well written, but I often worry about framework overuse.

What I mean specifically is that you don't really need the useRef to stop the timer, rather, using the useEffect together with a local variable to clear the time out.

Perhaps a better use case would've been to show how to have two different effects interact with the same timer, for instance, in your example there can be a useEffect handler which has a single responsibility to clear out timers, which might be needed in production a few times, in spite of growing complexity, while another effects take care of starting it.

Even better use case are audio/video tags which can be started/paused, or how to deal with stale values.

Good article anyway! Keep them coming!

Collapse
jamesncox profile image
James Cox Author

Thank you for reading and the feedback, Joseph!

Funny that you mention using useEffect to also stop the timer, with a local variable, because I tried that several different ways, and couldn't get the timer to stop immediately on pressing pause. I am sure there is a better way, I just don't know what that is (yet)!

I think for me the issue is having the setTimeout inside the conditional block (start === true) and accessing that variable to clearTimeout isn't possible.

That's why useRef made a lot of sense to me. Accessible basically anywhere!

But I am open to new ideas and solutions! If there is a better way, I would love to know what that is!

Collapse
icyjoseph profile image
Joseph

Mmm perhaps I am missing something, did you try this?

useEffect(() => {
     let timer;
     if (start === true) {
        timer = counter > 0 && setTimeout(() => setCounter(counter - 1), 1000)
     }
     return () => {
        clearTimeout(timer)
      }
  }, [start, counter, setCounter])

And we could even get rid of counter:

useEffect(() => {
     let timer;
     if (start === true) {
        timer = setTimeout(() => setCounter(x => x === 0 ? 0 : x - 1), 1000)
     }
     return () => {
        clearTimeout(timer)
      }
  }, [start, setCounter])