if I create a reaction in a with-let binding, it looks like I have to dispose it in the finally block. perhaps the macro should do this for us?
you were right, I can just use memoize instead of with-let and track if I already have a function that returns a reaction
memoize retains the cache indefinitely, prone to memory leaks.
oh that is good to know
I assumed they would be cached to the locally scoped function and would be gc'd with it
looking at cljs.core/memoize, it looks like the mem atom can be gc'd if nothing uses the returned function anymore
Ah yeah, that's true. I assumed you had something like (def f (memoize (...))).
local memoized functions are like lazy maps, pretty cool
finalized code for detecting intermediate changes inside a render batch, with examples I used to test: https://gist.github.com/shaunlebron/d6a681ce74f46cf1b23b2b7f07f14759
test-inner-flashes has a weird pattern of nested with-lets and track, but it seems to work, based on what I understood from the mouse-pos example, and things seem to dispose correctly. thanks p-himik for the insight on how they dispose
Don't have time right now to delve deeper into it, but it surely looks like some over-engineering. ;) A nested with-let, an immediately @'ed track... I could be wrong though!
Hmm, this is also what the mouse-pos demo in the docs was doing. Maybe there's a simpler way
If you create a reaction and do nothing else with it, no need to dispose! of it - there's nothing to dispose of.
If you also @ that reaction in that very component, the reaction will be registered with that component. When the component unmounts, the reaction will gets its watchers updated. If there are no watchers, the reaction will be disposed of automatically.
Just tested it - yep, seems to work that way.
hmm, I’m using a run!, might have to dispose that manually or rethink why I reached for that
trying to make a "flash" reaction:
(defn flash
"A reaction that returns any logical true result of pred whenever r* changes.
The reaction’s value resets to nil after `ms` milliseconds, unless interrupted by another logical true r*."
[r* pred ms]
(let [flash-val* (r/atom nil)
timeout* (volatile! nil)]
(ra/run!
(when-some [v (pred @r*)]
(reset! flash-val* v)
(js/clearTimeout @timeout*)
(->> (js/setTimeout #(reset! flash-val* nil) ms)
(vreset! timeout*))))
flash-val*))another problem is that we sometimes receive two events in the same rendering frame that update our state, and our view misses the intermediate state, so we can’t even use a "flash" reaction like this because I think updates are batched
maybe I can call add-watch on our state ratom and r/flush when certain critical values change
looks like the flush worked
this seems to dispose now:
(defn flash
"A reaction that returns any logical true result of pred whenever r* changes.
The reaction’s value resets to nil after `ms` milliseconds, unless interrupted by another logical true r*."
[r* pred ms]
(let [flash-val* (r/atom nil)
timeout* (volatile! nil)
pred* (ra/make-reaction
(fn []
(when-some [v (pred @r*)]
(reset! flash-val* v)
(js/clearTimeout @timeout*)
(->> (js/setTimeout #(reset! flash-val* nil) ms)
(vreset! timeout*))
v))
:on-dispose (fn [] (println "pred* disposing"))
)]
(ra/make-reaction
(fn []
@pred*
@flash-val*)
:on-dispose (fn [] (println "flash disposing")))))