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

时间:2017-12-19 10:38:03

标签: clojure clojurescript 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]])))

当我在内部输入组件中输入数据时,我需要更新本地状态表单。当外部组件卡输入更新时,我想将我的表单从参数重置为新的 title prop。我怎样才能做到这一点?

我尝试将(reset! form title)放在内部输入组件中的let和fn之间,但它无济于事

1 个答案:

答案 0 :(得分:1)

您可以使用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更改时可以安全地调用...不会发生任何事情。