Fork me on GitHub
#re-frame
<
2022-11-04
>
Valentin Mouret15:11:35

Hey peeps, I am beginner in frontend and re-frame/reagent and I am facing an issue. Context: I have a Clojure map that I want to edit in a text area. For that, I have a component that roughly looks like this:

(defn json-panel
    [original] ;; Initial value of the map
     ;; State of the data the user is updating
    (let [state (-> original (or {}) (clj->js) (js/JSON.stringify true 2) (reagent/atom))]
      (fn [original]
        (let [parsed (->json @state)]
          [:textarea {:on-change #(reset! state (.. % -target -value))
                      :value @state}]
          [:button {:on-click #(dispatch [::set-user-data parsed])} \"Save\"]))))
This works fine, but when I change the props (`original`) in my example, the text area stays the same. What I understand is that only the inner function is rendered, so only it «knows» that original has changed. However, the atom is in the outter function. What’s the proper way to reset the state (atom) here?

Valentin Mouret15:11:23

I looked at reagent’s form-1, 2, and 3s, and it’s not clear if I should use form-3 on such a simple example.

Valentin Mouret15:11:33

A hack could be to put the props in the state and have the rendered detect if the props have changed. But this sounds horrendous. 😄

lispers-anonymous15:11:32

In the outer function you can name your original argument something different from your inner original argument. This would allow them to be compared in the inner function and reset when they are different

Valentin Mouret15:11:49

Oooh, that’s smart. Having another atom that would this value and reseting when it changes. Thanks, I had not seen this option! :)

lispers-anonymous15:11:47

I’m not suggesting another atom, but just changing the argument name and resetting the one state atom.

lispers-anonymous15:11:04

It would override and changes that the user made to the state though.

Valentin Mouret15:11:01

But that would work only once, right? At first, props are the same, so no resets. Then props change -> render detects a change, the atom can be reset. But then, every subsequent update will reset the atom, won’t it? Because the very first props never change.

lassemaatta15:11:04

I recall seeing some code a long time ago where two atoms (well I guess you could store the whole state in a single atom with a map) were used for that. One kept track of the current value (similar to your code) and the other kept track of the previous value of original and then you had code to detect when the outside value changed, do stuff and then update the "previous" value.

👍 1
Valentin Mouret15:11:58

I guess I’ll to this way then! Thanks :)

lispers-anonymous16:11:07

> But then, every subsequent update will reset the atom, won’t it? Because the very first props never change. Yeah that is right, the two atoms strategy might be the way to go then. You can also use one atom, with a map with keys for original value and current value.