Fork me on GitHub
#reagent
<
2021-03-25
>
wombawomba17:03:47

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?

lilactown19:03:53

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

lilactown19:03:08

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

lilactown19:03:13

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"}}
   [component-that-users-context]])

juhoteperi19:03:33

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 []
  [context-provider
   [:f> component-that-uses-contect]])

🎯 3
juhoteperi19:03:12

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.

wombawomba22:03:34

cool, thanks!

wombawomba22:03:59

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