+8

Problem with React context API and useEffect hook

Hey everybody. So I have a timer component and 4 option components. I want behavior that if timer is out of time then it should move to next question and same thing + timer set to 0 should happen if any option is clicked. It works fine with timer, like if it runs out of time then next question is displayed but once I use option button then it behaves different and timer also runs twice speed. Here is my code, please can anyone check out where did I make mistakes? https://code.sololearn.com/W6g76LukrNky/?ref=app

5/22/2020 1:11:38 PM

🔫 Rick Grimes

25 Answers

New Answer

+9

As suggested by calvin: Different useEffect for timer and currentIndex. I used setInterval instead of setTimeout https://code.sololearn.com/WsU4oM3cEBi6/?ref=app

+7

Putting the interval/timeout value in the hook state just ensures that we have the updated value. you can test this code to see what happens when declaring the value without useState: https://code.sololearn.com/WY3PM3Qj82Z1/?ref=app If you don't need to control the clear functions from within the component you can use a unmount useEffect and initialize the interval in there (and return a function that clears it)

+6

🔫 Rick Grimes better use separate useEffect for timer and currentIndex.

+6

🔫 Rick Grimes timeouts and intervals can be tricky with hooks (and in react lifecycles in general)

+4

Calviղ the variable name is timerInterval, but the functions are setTimeout and clearTimeout 😂

+4

Don't be afraid of having multiple useEffect hooks Just try to keep them as tidy as possible

+3

How about hositing the timer to a global level. Explicitly, adding the timer variable to the reducer state, and reseting to 0 inside the dispatch SET_QUESTION type?

+3

🔫 Rick Grimes since it's setTimeout, you can safely clearTimeout whenever useEffect runs, no need to check for timerTimeout!=null

+3

Calviղ Okay let me try that way and see if I can solve it otherwise I'll have to go by way suggested by Gordon I actually thought about that way but then I thought it might be not the best way to do it, so dropped that idea 😬

+2

If you put setInterval in useEffect with timer trigger, the timer speed would be double whenever timer is triggered. You can use setTimeout instead, let timer retriggers the interval.

+2

Opps...i got confused 😅

+2

Calviղ sorry, my bad. I was trying to do this with interval but after some Google search I found this way and I forgot to change variable name Gordon Do i have to use multiple useEffects?

+2

🔫 Rick Grimes i notice currentIndex is increment when option is selected, and it triggers useEffect function running. Should currentIndex triggered, run clearTimeout while the timeout is still counting? instead of setting setTimeout again.

+2

🔫 Rick Grimes I noticed that timerTimeout is always null, so currentIndex has no way to clearTimeout.

+2

I tried to edit code as Gordon suggested, the only problem now is that once I use option to change question index then timer is running at twice speed. https://code.sololearn.com/WwiPUR4UaKN8/?ref=app

+2

🔫 Rick Grimes did you clearTimeout when currentIndex triggered?

+2

🔫 Rick Grimes I think timerTimeout should be in global state too..

+2

Burey okay that's pretty neat example. I never thought of making it that way. Thank you so much for that.

+2

Calviղ issue is solved but still I tried to do clearTimeout for currentIndex useEffect which causes timer to never start (just updated code) Calvin and Gordon thanks to you two for taking some time for me. :)

+2

Yes, indeed it is. I almost wasted 2 hours looking for solution