@lilactown Thank you for Helix. One more reason (pun) to stay with clojurescript.
How do I create a react hook to use with re-frame? I see an example https://cljdoc.org/d/lilactown/helix/0.0.13/doc/integrating-with-other-libraries but it’s incomplete. Here’s what I’ve tried so far:
(defn watch-ratom
[f]
(let [tracker (rc/track! f)]
#(rc/dispose! tracker)))
(defn use-sub [query]
(let [subscription (hhooks/use-memo :auto-deps
{:get-current-value (fn []
@(rf/subscribe query))
:subscribe watch-ratom})
value (hhooks/use-subscription subscription)]
value))
This doesn’t work as I’m ending up with an infinite re-render.this channel is for the Helix library, you should try asking at #re-frame
Actually, I believe this is appropriate for this channel as I’m writing hooks for use with helix. It’s more likely someone here has had to write some kind of use-sub
for a reagent atom.
hey Emmanuel. this channel is fine to ask your question. Thanks wilker for trying to moderate, though, as we do get questions that are really better served by #reagent and #re-frame sometimes 🙂
first reaction is that I'm not sure your watch-ratom
is correct
the f
passed to watch-ratom
is a callback that should be called when you want React to re-render, and I think in this case track!
is going to synchronously call that function. that would explain why you're getting in an infinite loop
I think you need to close over the reaction returned by the subscribe
and then track that
this is pretty close to what we use at work:
(let [reaction (hhooks/use-memo
[query]
(rf/subscribe query))
sub (hhooks/use-memo
[reaction]
{:get-current-value #(deref reaction)
:subscribe (fn [f]
(let [tracker (r/track! #(f @reaction))]
#(r/dispose! tracker)))})]
(hhooks/use-subscription sub))
let me know if that works or not. the use-subscription
hook hasn't been used in production yet. I'm hoping that it's not due to that but it might also be worth trying React's use-subscription
if you continue to have issues
Oh I see. That worked for me!
I saw that the callback doesn’t currently accept any argument which is why I was calling the function without the reaction
I’m actually surprised that #(f @reaction)
works even though f
is a 0 arity function
yeah I suppose to be stricter, it should be:
(fn []
@reaction ;; for tracking side effect
(f))
you could also use add-watch
/ remove-watch
I think
the important thing is to not call f
unless reaction
has changed
using track!
like we are might cause a double render on mount since the function passed to track!
gets called on mount to figure out what reactions to track
#(f @reaction)
works because JS functions don't enforce arity, which is different than Clojure. CLJS does have some static compile-time checks but it's a best effort kind of thing
Gotcha. Thank you!
ah, cool, didn't realize Helix had integration docs with other react wrappers 👍