为什么试剂在状态变化时不重新呈现我的试剂形式
Why does reagent not re-render my reagent-form on a state change
我需要创建一个包含 select 字段的表单,其中的选项取决于当前可用的邮件帐户。页面加载后,我在 API 请求中检索这些邮件帐户。
以下函数使用 select 元素创建表单。
(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]))))
pprint
给出了以下输出:
;; 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"]]
我的问题是我页面上的 select 保持空白,就好像 select 没有重新呈现一样。
附录
我想我忘了添加一些代码:
我将此表单包装在一个 KIOO 组件中,我在其中取消引用我的 state
原子。
(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)])})
此组件然后调用我的 render-mail-account-select
函数并且应该正确地重新呈现表单。
您需要取消对 Reagent 的 Ratom 的引用,以了解当 Ratom 发生变化时需要再次调用哪些函数。取消引用需要在 render-mail-account-select
内的匿名函数或它调用的函数之一中发生。我看不到这里发生任何取消引用?
有关 Reagent 渲染的更多详细信息,请参阅文档 here。
如前所述,渲染函数必须引用状态原子中的某些内容,以便知道何时需要重新渲染。但是,如果您还希望显示的表单选择 'default' 值,则还需要设置状态原子。
绑定字段调用会将您的表单与状态原子相关联。如果状态原子中没有任何内容,则形式将为 'blank',即所选元素的 none。如果这是你想要的,那应该没问题。但是,如果您想要选择一个值,那么您应该将该值放入原子中。例如,如果您希望第一项已被选中,则将 :24 放入状态原子中,即
(swap! form-state assoc :mail-account :24)
请注意,我不确定您的选项定义是否正确。文档似乎表明您只需要 :key 属性以及该属性中的值(作为关键字)。我没有查看源代码来确认这一点,但是 none 示例也使用了 :value 属性。
如果您在渲染函数的开头进行交换,那么状态原子将被引用,并且您的组件在每次使用新参数调用时都应该重新渲染。当我说 'render function' 时,在这种情况下,我指的是匿名函数,而不是创建状态原子的外部函数。
我需要创建一个包含 select 字段的表单,其中的选项取决于当前可用的邮件帐户。页面加载后,我在 API 请求中检索这些邮件帐户。
以下函数使用 select 元素创建表单。
(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]))))
pprint
给出了以下输出:
;; 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"]]
我的问题是我页面上的 select 保持空白,就好像 select 没有重新呈现一样。
附录
我想我忘了添加一些代码:
我将此表单包装在一个 KIOO 组件中,我在其中取消引用我的 state
原子。
(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)])})
此组件然后调用我的 render-mail-account-select
函数并且应该正确地重新呈现表单。
您需要取消对 Reagent 的 Ratom 的引用,以了解当 Ratom 发生变化时需要再次调用哪些函数。取消引用需要在 render-mail-account-select
内的匿名函数或它调用的函数之一中发生。我看不到这里发生任何取消引用?
有关 Reagent 渲染的更多详细信息,请参阅文档 here。
如前所述,渲染函数必须引用状态原子中的某些内容,以便知道何时需要重新渲染。但是,如果您还希望显示的表单选择 'default' 值,则还需要设置状态原子。
绑定字段调用会将您的表单与状态原子相关联。如果状态原子中没有任何内容,则形式将为 'blank',即所选元素的 none。如果这是你想要的,那应该没问题。但是,如果您想要选择一个值,那么您应该将该值放入原子中。例如,如果您希望第一项已被选中,则将 :24 放入状态原子中,即
(swap! form-state assoc :mail-account :24)
请注意,我不确定您的选项定义是否正确。文档似乎表明您只需要 :key 属性以及该属性中的值(作为关键字)。我没有查看源代码来确认这一点,但是 none 示例也使用了 :value 属性。
如果您在渲染函数的开头进行交换,那么状态原子将被引用,并且您的组件在每次使用新参数调用时都应该重新渲染。当我说 'render function' 时,在这种情况下,我指的是匿名函数,而不是创建状态原子的外部函数。