reagent 2025-02-24

Hello folks I'd like to share solution of an issue, that may help others. Setup: I'm using reagent@1.1.0, react@17.0.2 and antd@4.23.6 I was using the input like this, that I believe that is the "reagent default" option:

(defn ui-input-v1
  [{:keys [*value]}]
  [:> antd/Input {:value    @*value
                  :onChange (fn [e]
                              (reset! *value (.-value (.-target e))))}])
;; buggy version. the cursor keeps jumping to the end of input
#_[ui-input-v1 {:*value (r/atom "abc")}]
but this was causing the cursor to jump to the end while editing. I've been living with this for a few months. Today I discovered that if I use the new :f>, it will fix my issue:
(defn ui-input-v2
  [{:keys [*value]}]
  (let [[value on-change] (react/useState (str @*value))]
    (react/useEffect (fn []
                       (reset! *value value)))
    (react/createElement antd/Input #js{:value    value
                                        :onChange (fn [e]
                                                    (on-change (.-value (.-target e))))})))
;; NOT fully functional version (read the thread)
#_[:f> ui-input-v2 {:*value (r/atom "abc")}]

In the second version, if something else changes the input ratom externally, will the input see the change?

good catch. I think that I need another useEffect with add-watch and something to "cleanup"

Well, the ratom is deref'ed in the render function. But I have no clue how it works in that specific case with two hooks and a function component.

(react/useEffect (fn []
                   (let [ident (keyword (str (random-uuid)))]
                     (add-watch *value ident
                       (fn [_ _ prev next-value]
                         (prn [:prev prev next-value])
                         (on-change next-value)))
                     (fn []
                       (some-> *value (remove-watch ident)))))
  #js[])
This hook tecnically works, goes into loop with the prev state

OK. I will not use the ratom. :initial-state and :on-change will do for now

@p-himik do you understand why reagent has this issue with antd input's? (or antd has this issue with reagent components?!) Does this problem have a name?

It's a common thing that for :input and :textarea Reagent fixes on its own end. There are some examples of doing it for thirdparty libraries used from Reagent. I usually use the double ratom approach - what re-com uses.

@souenzzo It happens because Reagent is batching the changes on the ratoms. There is a way to workaround the problem: https://github.com/reagent-project/reagent/blob/master/doc/ControlledInputs.md