helix

https://github.com/Lokeh/helix
2020-12-29T14:16:11.250800Z

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

1
Emmanuel John 2020-12-29T18:25:27.254300Z

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.

wilkerlucio 2020-12-29T19:07:20.254800Z

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

Emmanuel John 2020-12-29T19:17:30.255Z

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.

lilactown 2020-12-29T19:18:44.255300Z

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 🙂

lilactown 2020-12-29T19:19:13.255600Z

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

lilactown 2020-12-29T19:21:01.255800Z

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

lilactown 2020-12-29T19:21:51.256Z

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

lilactown 2020-12-29T19:30:52.256200Z

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

lilactown 2020-12-29T19:33:11.256400Z

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 John 2020-12-29T19:51:39.256600Z

Oh I see. That worked for me!

Emmanuel John 2020-12-29T19:52:30.256800Z

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

Emmanuel John 2020-12-29T19:54:46.257Z

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

lilactown 2020-12-29T20:04:50.257200Z

yeah I suppose to be stricter, it should be:

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

lilactown 2020-12-29T20:05:16.257400Z

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

lilactown 2020-12-29T20:06:10.257600Z

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

lilactown 2020-12-29T20:07:41.257800Z

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

lilactown 2020-12-29T20:09:26.258100Z

#(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 John 2020-12-29T20:11:12.258300Z

Gotcha. Thank you!

wilkerlucio 2020-12-29T20:40:56.258500Z

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