如何将新道具传递给 Reagent 中组件的状态?

How to pass new props to state of acomponent in Reagent?

我有一个组件:

(defn inner-input [cljs_element activeEl title]
  (let [form (atom title)]
    (fn [cljs_element activeEl title]
      [:input {:type "text"
           :onChange #(reset! form (.. % -target -value))
           :on-blur #(change-title cljs_element (.. % -target -value))
           :style {:display (if (:active (:node cljs_element)) "block" "none")
                   :width (* (+ 1 (count @form)) 8)
                   :max-width 730
                   :min-width 170}
           :value @form}])))

它嵌套在其他组件中:

(defn card-input [cljs_element activeEl]
  (fn [cljs_element activeEl]
    (let [title (:title (:node cljs_element))]
      [:div
        [inner-input cljs_element activeEl title]])))

当我在 inner-input 组件中输入数据时,我需要更新本地状态 form。当外部组件 card-input 更新时,我想将我的表单重置为参数中的新 title 道具。我怎样才能做到这一点?

我尝试在 inner-input 组件中将 (reset! form title) 放在 let 和 fn 之间,但这无济于事

您可以使用 reagent/track! 收听标题的更改,使用 reagent/dispose 停止收听。您也可以使用 add-watch 和 remove-watch,但 track 是更方便的语法。

(defn inner-input [title]
  (reagent/with-let
    [form (reagent/atom @title)
     watch (reagent/track! (fn [] (reset! form @title)))]
    [:label
     "Inner input"
     [:input {:on-change (fn [e]
                           (reset! form (.. e -target -value)))
              :on-blur (fn [e]
                         (reset! title (.. e -target -value)))
              :value @form}]]
    (finally
      (reagent/dispose! watch))))

(defn card-input []
  (reagent/with-let
    [title (reagent/atom "hello")]
    [:div
     [:label "Title"
      [:input {:on-change (fn [e]
                            (reset! title (.. e -target -value)))
               :value @title}]]
     [inner-input title]]))

现在,如果您输入内部输入,当您退出输入框时,它只会更新外部,但更改外部标题会立即更改内部标题。那是你想要的吗?

但是如果您不想将标题作为 ratom 传递而必须将其作为值传递,那么您可以将它与之前的值进行比较以确定它是否已更改,然后重置表单只有当它改变时。

(when (not= @previous-title title)
  (do (reset! previous-title title)
      (reset! form title)))

此代码可以在渲染中看到,因为当 form 更改时调用是安全的...不会发生任何事情。