react

"mulling over state management stuff"
martinklepsch 2020-11-20T14:27:06.029700Z

I’m trying to create a hook that fires a timer every second and updates some state in the component. A part of this state is a counter (how often the timer ran basically) and I’m a little stuck on how to swap! vs reset! state in an effect so to say. I guess with state this isn’t really intended to work so I also looked into refs, which I think would work but then again that comes with other inconveniences.

martinklepsch 2020-11-20T14:27:37.030500Z

(rum/use-effect! (fn []
                       (let [timer (js/setInterval #(do (js/console.log :secs-passed secs-passed)
                                                        (set-now! (c-util/server-now))
                                                        (set-secs-passed! (inc secs-passed)))
                                                   1000)]
                         (fn cleanup-timer [] (js/clearInterval timer))))
                     [something])

martinklepsch 2020-11-20T14:28:22.031100Z

Another approach I’ve seen is to just not use setInterval and instead use a timeout and have the effect run every time the component is updated

martinklepsch 2020-11-20T14:28:44.031400Z

Thinking about it a bit more, that might actually just do the job

martinklepsch 2020-11-20T14:35:25.032600Z

Yeah, that works. Still a little weird to do it this way instead of only having the effect run once. I guess I could somehow write a custom hook that passes the number of times the interval ran to a callback or something like that?

martinklepsch 2020-11-20T14:37:24.033Z

also wow, https://www.react-spring.io/ looks like it’s come a long way since I last looked at it

martinklepsch 2020-11-20T14:37:33.033400Z

pretty excited to play with it some day

ordnungswidrig 2020-11-20T15:31:35.035100Z

I think the proper approach is to setInterval in useEffect and return a function that will cancel it. In the timer callback you can use the setter of useState to update.

orestis 2020-11-20T16:04:49.035900Z

I’m using react spring currently, it’s neat but I would wish for something even more high level.

orestis 2020-11-20T16:05:53.037300Z

Regarding useEffect, I think you need to be explicit and pass in an empty dependency array to make it work just on mount, otherwise it will fire on every render...

martinklepsch 2020-11-20T17:12:21.038400Z

So the code above uses the setter of state (`set-secs-passed!` ) but the issue is that the (inc secs-passed) captures the value of the first render (`secs-passed` is also state)

dominicm 2020-11-20T17:25:30.038500Z

@martinklepsch set-secs-passed! will support taking a function, so (set-secs-passed! inc)

dominicm 2020-11-20T17:25:50.038600Z

(assuming it works like react/setState)

martinklepsch 2020-11-20T18:02:16.038900Z

oh what, really? did not know!

martinklepsch 2020-11-20T18:03:04.039300Z

@dominicm thanks for pointing that out, didn’t realize 🙂

dominicm 2020-11-20T18:04:08.039400Z

@martinklepsch Unlike swap! it doesn't take varargs :( but it's good for this use-case.

🙌 1
lilactown 2020-11-20T22:19:27.039700Z

helix's use-state does 😉

👍 1