fulcrologic / fulcro

A library for development of single-page full-stack web applications in clj/cljs
http://fulcro.fulcrologic.com
MIT License
1.55k stars 140 forks source link

Root form refresh (render) not working #118

Closed RokLenarcic closed 6 years ago

RokLenarcic commented 6 years ago

I've found one major and one minor issue when working with forms.

Here's steps to reproduce:

  1. Create a new fulcro project using lein new fulcro.

  2. Open project.clj and change fulcro version to 2.1.0-SNAPSHOT (although it may also be present in previous versions)

  3. Open root.cljc and add require [fulcro.ui.forms :as f].

  4. Replace root.cljc content below ns declaration with:

;; The main UI of your application

(m/defmutation simple-edit
  "Simple mutation that updates variable at the path, doesn't operate with non-normalized"
  [{:keys [path fn]}]
  (action [{:keys [state]}]
    (swap! state update-in path fn)))

(defsc PersonForm [this {:keys [person/id person/name person/active] :as form}]
  {:query [f/form-key :person/id :person/active :person/name]
   :form-fields [(f/id-field :person/id) (f/text-input :person/name) (f/checkbox-input :person/active :default-value true)]
   :ident [:person/by-id :person/id]
   :initial-state (fn [params] (f/build-form PersonForm {:person/id 1 :person/active false :person/name "Mike"}))}
  (dom/div nil
    (dom/div nil (f/form-field this form :person/name))
    (dom/button #js {:onClick (fn [evt] (prim/transact! this `[(simple-edit {:path [:person/by-id ~id :person/active] :fn ~not}) f/form-root-key]))}
      "CLICK ME")))

(def ui-person-form (prim/factory PersonForm {:key-fn :person/id}))

(defsc TopForm [this {:keys [modal-item] :as form}]
  {:form-fields [(f/subform-element :modal-item PersonForm :one :isComponent false)]
   :query [f/form-root-key f/form-key {:modal-item (prim/get-query PersonForm)}]
   :ident (fn [] [:topform :singleton])
   :initial-state (fn [params] (f/build-form TopForm {:modal-item (prim/get-initial-state PersonForm {})}))}
  (let [{:keys [person/name person/active]} modal-item]
    (dom/div nil
      (dom/div nil (if active (str "! " name) (str "# " name)))
      (dom/div nil
        (ui-person-form modal-item)))))

(def ui-top-form (prim/factory TopForm))

(defsc Root [this {:keys [ui/react-key top-form]}]
  {:query [:ui/react-key {:top-form (prim/get-query TopForm)}]
   :initial-state (fn [params] {:top-form (prim/get-initial-state TopForm {})})}
  (dom/div #js {:key react-key}
    (dom/div nil "Title")
    (ui-top-form top-form)))

Let's take a moment here to examine what is being done. We have an inner form which edits two properties, name and active. Name is being edited through built-in forms input field and active boolean is being edited through the button and a custom mutation. We have a top-level form which has a div that is dependent on both properties. For that to work it needs to re-render whenever they change which is accomplished by reading f/form-root-key.

Run the client and server. Open fulcro inspect. You'll see that DB is what you'd expect.

Here's the unexpected:

Writing in the input box doesn't change the text in the top-form div, because it's not re-rendered. If you open fulcro-inspect you'll see that DB is being updated correctly and the transactions tab will show that transactions are being done with correct follow-up reads on f/form-root-key.

If you click the button instead, you'll see that the text in top-form div updates as expected and flips between !/#.

Now here's the other weird behaviour: even though, unlike the input box, button works as expected, its transactions never show up in fulcro inspect transaction tab (???).

awkay commented 6 years ago

Thanks for the repro case. I'll look into it probably later today. May be related to #116. I have not confirmed where that one messes up entirely yet either.

awkay commented 6 years ago

Confirmed. It looks like follow on reads got disconnected in transact! somehow...

awkay commented 6 years ago

Fixed in 2.0.1