This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-09-26
Channels
- # announcements (3)
- # babashka (23)
- # beginners (54)
- # calva (9)
- # cider (8)
- # clj-kondo (18)
- # cljsrn (25)
- # clojure (69)
- # clojure-australia (1)
- # clojure-europe (7)
- # clojure-spec (13)
- # clojure-uk (1)
- # clojurescript (122)
- # conjure (8)
- # cursive (15)
- # defnpodcast (9)
- # deps-new (2)
- # emacs (22)
- # fulcro (10)
- # graalvm (36)
- # luminus (5)
- # meander (5)
- # minimallist (1)
- # observability (6)
- # off-topic (54)
- # reagent (8)
- # reitit (2)
- # releases (1)
- # reveal (25)
- # shadow-cljs (21)
- # tools-deps (50)
- # vrac (1)
- # xtdb (2)
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.