Hello
I'm having trouble getting a form 3 CodeMirror component to re-render when I want it to.
I have the component model-input
, which is instantiated with a 'selected-measure' atom received from a subscription. I extract the code for the selected measure, and wrap in local-state atom code
. I then instantiate the codemirror
component with the code
, and the component unwraps it and displays it.
The model-input
also has a dropdown which selects the measure and dispatches something that should trigger the model-input
to re-render, and I would assume the codemirror
also. I can see the local state in model-input
is changing when the dropdown is changed, but the codemirror is not, and I don't get why.
I'm guessing I'm either missing something in the form 3 component, or not understanding the re-render logic. Any thoughts?
https://github.com/RedPenguin101/modeldsl/blob/codemirror-redo/src/model_dsl/frontend/main.cljs
Thanks in advance
Here's an abbreviated version of the code if that's simpler
(defn app []
,,,
[:div#input.columns
[:div#model.column
[:h4.title.is-4 "Model"]
[model-input (rf/subscribe [:selected-measure])]]]
,,,)
(defn model-input [selected-measure-atom]
(fn [selected-measure-atom]
(let [{:keys [name code]} @selected-measure-atom
code (r/atom code)]
[:div
,,,
[measure-dropdown]
[codemirror code {:name name}]
,,,])))
(defn codemirror [value-atom options update]
(let [options (merge {:mode "clojure"} options)]
(r/create-class
{:reagent-render (fn [] [:div])
:component-did-mount
(fn [component]
(let [editor (create-codemirror
(rd/dom-node component)
(assoc options
:value @value-atom))]
(.on editor "change"
#(reset! value-atom (.getValue editor)))))})))
(defn create-codemirror [elem options]
(js/CodeMirror.
elem
(clj->js options)))
I tried adding a component-did-update
key to codemirror
but it started doing some weird things, so I thought that was probably the wrong approach.
value-atom
is never updated. You should get it from the new properties in the :component-did-update
function.
Would value-atom
(which is actually code
) not be updated when the :selected-measure
subscription fires in app
?
codemirror
is a form-3 component. Its [value-atom options update]
arguments are used only when it's mounted. All the subsequent updates are passed to :component-did-update
.
Similar to form-2 components - the outer function receives its arguments when the component is mounted. All the subsequent updates change only the arguments of the inner function. Unless there's a :key
metadata, but that's a whole other story.
Thanks! Not sure I've got my head around it TBH, but after adding the :component-did-update
it is working now.
Reagent and re-frame documentation is a great read that answers many similar questions.