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?
this is really a function of how React works. component's render functions are not called until later
there is a React solution: Context. but it is painful to use from Reagent
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]])
but watch out for this gotcha: https://github.com/reagent-project/reagent/issues/371
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]])
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.
cool, thanks!
I'll only want to do this in a few places, so I'm fine with the solution being a bit messy 🙂