Fork me on GitHub
#helix
<
2020-12-29
>
geraldodev14:12:11

@lilactown Thank you for Helix. One more reason (pun) to stay with clojurescript.

3
Emmanuel John18:12:27

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.

wilkerlucio19:12:20

this channel is for the Helix library, you should try asking at #re-frame

Emmanuel John19:12:30

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.

lilactown19:12:44

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 🙂

lilactown19:12:13

first reaction is that I'm not sure your watch-ratom is correct

lilactown19:12:01

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

lilactown19:12:51

I think you need to close over the reaction returned by the subscribe and then track that

lilactown19:12:52

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))

lilactown19:12:11

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

Emmanuel John19:12:39

Oh I see. That worked for me!

Emmanuel John19:12:30

I saw that the callback doesn’t currently accept any argument which is why I was calling the function without the reaction

Emmanuel John19:12:46

I’m actually surprised that #(f @reaction) works even though f is a 0 arity function

lilactown20:12:50

yeah I suppose to be stricter, it should be:

(fn []
  @reaction ;; for tracking side effect
  (f))

lilactown20:12:16

you could also use add-watch / remove-watch I think

lilactown20:12:10

the important thing is to not call f unless reaction has changed

lilactown20:12:41

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

lilactown20:12:26

#(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

Emmanuel John20:12:12

Gotcha. Thank you!

wilkerlucio20:12:56

ah, cool, didn't realize Helix had integration docs with other react wrappers 👍