fulcro

oliver 2025-11-29T17:54:31.014569Z

Hi! I'm learning Fulcro (coming from Re-frame) and encountered a strange issue with controlled text inputs not visually updating when their value changes via mutations, even though the component seemingly re-renders correctly. Here's what I have:

(defmutation increment-counter [{:keys [amount]}]
  (action [{:keys [state]}]
    (swap! state update-in [:component/id :counter :counter/value] + amount)))

(defmutation reset-counter [{:keys [value]}]
  (action [{:keys [state]}]
    (swap! state assoc-in [:component/id :counter :counter/value] value)))

(defsc Counter [this {:counter/keys [value]}]
  {:query [:counter/value]
   :ident (fn [] [:component/id :counter])
   :initial-state (fn [_] {:counter/value 0})}

  (js/console.log "Counter rendering with value:" value)  ;; Logs correctly: 0, 1, 2...

  (dom/div :.counter
    (dom/h3 "Counter Example")
    (dom/p (str "Count: " value))  ;; Updates correctly to "Count: 1"

    ;; Buttons work fine - trigger mutations correctly
    (dom/button {:onClick #(comp/transact! this [(increment-counter {:amount 1})])}
      "+1")

    ;; Debug: shows we're passing the right value
    (dom/span {:style {:color "red"}} (str " [value=" value "] "))  ;; Shows [value=1]

    ;; This input does NOT visually update when buttons are clicked
    (dom/input {:type "text"
                :value (str value)
                :onChange (fn [ev]
                           (let [v (js/parseInt (.. ev -target -value) 10)]
                             (when-not (js/isNaN v)
                               (comp/transact! this [(reset-counter {:value v})]))))})))
When I click "+1": - Database updates correctly - Component re-renders (console logs "Counter rendering with value: 1") - The "Count: " text updates to show "1" - The debug span shows [value=1] - ☇ *The actual input field still shows "0"* Observations: 1. *Hot reload DOES update the input* - when I save the file and shadow-cljs hot reloads, the input field updates to the current value 2. I've never seen this behavior with Re-frame (also uses React) 3. Tried both type="number" and type="text" - same issue Workaround: Adding a :key that changes with the value forces it to work:
(dom/input {:key (str "counter-input-" value)  ;; Forces re-mount
            :type "text"
            :value (str value)
            :onChange ...})
This works but causes the input to lose focus while typing (because React destroys/recreates the element). Obviously I'm doing seomthing wrong *What's the proper pattern for controlled inputs in Fulcro?* Should inputs be separate components with their own idents? Any insights appreciated! Using Fulcro 3.9.0-rc9 with shadow-cljs 3.2.0.

✅ 1
oliver 2025-12-01T17:03:58.037099Z

Downgrading Fulcro and Reagent indeed solved this. Thank you for taking the time and for your tireless work on Fulcro!

tony.kay 2025-11-30T20:25:38.780359Z

I’m still working on the react weirdness around inputs in 3.9.0. Always use the latest RC if you’re going to play with it. If you’re learning I would recommend using the last stable release. I suspect the RC is your problem. Also use React 18 if you’re learning for now. You’re welcome to try the latest RC (that should fix it), but if you’re reporting learning errors it’s safest to use a stable version.