Search code examples
clojurescriptreagentreagent-forms

Why does reagent not re-render my reagent-form on a state change


I need to create a form containing a select field where the options depend on the currently available mail accounts. I retrieve these mail accounts in a API request after the page has loaded.

The following function creates the form with the select element.

(defn create-options [mail-accounts]
  (for [m mail-accounts]
    [:option {:key (keyword (str (:id m)))
              :value (:id m)}
     (:name m)]))

(defn render-mail-account-select [mail-accounts]
  (let [form-state (r/atom {})]
    (fn [mail-accounts]
      (let [form [:form.mailing-form.form-horizontal
                  (into [:select.form-control {:field :list :id :mail-account}]
                        (create-options mail-accounts))]]
        (pprint form)
        [bind-fields form form-state]))))

The pprint gives me the following output:

;; Before the mail-accounts are loaded
[:select.form-control {:field :list, :id :mail-account}]

;; After the state update containing the mail accounts
[:select.form-control
 {:field :list, :id :mail-account}
 [:option {:key :24, :value 24} "First mail account name"]
 [:option {:key :25, :value 25} "Second mail account name"]]

My problem is that the select on my page stays empty as if the select does not get re-rendered.

Addendum

I think I forgot to add some code: I am wrapping this form in a KIOO component where I dereference my state atom.

(defsnippet choose-account-panel "html/static-panel.html" [:div.panel]
  []
  {[:h4.panel-title] (content "3. Mail Account wählen")
   [:div.panel-body] (content [render-mail-account-select (:mail-accounts @state)])})

This component then calls my render-mail-account-select function and should re-render the form properly.


Solution

  • You need to dereference a Ratom for Reagent to know which functions need to be called again when that Ratom changes. That dereferencing needs to happen within the anonymous function inside render-mail-account-select, or one of the functions that it calls. I can’t see any dereferencing happening here?

    See the docs here for more details on Reagent’s rendering.