A minimalistic ClojureScript interface to React.js
wombawomba 2021-03-25T17:39:47.042Z

I'd like to use bindings to control how certain components are rendered, but it's not working (because Reagent doesn't render 'inner' elements (e.g. [foo]) until after the original scope has been exited). Is there a way around this?

lilactown 2021-03-25T19:14:53.043800Z

this is really a function of how React works. component's render functions are not called until later

lilactown 2021-03-25T19:15:08.044200Z

there is a React solution: Context. but it is painful to use from Reagent

lilactown 2021-03-25T19:21:13.047600Z

you can try something like:

(def my-context (react/createContext {:some-value "default"}))

(def my-context-provider (.-Provider my-context))

(def my-context-consumer (.-Consumer my-context))

(defn component-that-uses-context []
  [:> my-context-consumer
    (fn [{:keys [some-value]}]
      (r/as-element [:div "some-value is: " some-value])]))

(defn component-that-provides-context []
  [:> my-context-provider {:value {:some-value "not default"}}

lilactown 2021-03-25T19:22:50.048Z

but watch out for this gotcha:

juhoteperi 2021-03-25T19:25:33.050100Z

useContext Hook can be useful, just remember to use this component with :f>:

(defn component-that-uses-context []
  (let [{:keys [some-value]} (react/useContext my-context)]
      [:div "some-value is: " some-value]))

(defn foo []
   [:f> component-that-uses-contect]])

juhoteperi 2021-03-25T19:27:12.051400Z

Bindings are also impossible to use, as it is not certain that the parent render has been called when a element render is called. If ratoms or such triggers the re-render, only that element and its children are re-rendered.

wombawomba 2021-03-25T22:46:34.051800Z

cool, thanks!

wombawomba 2021-03-25T22:48:59.052500Z

I'll only want to do this in a few places, so I'm fine with the solution being a bit messy 🙂