簡體   English   中英

clojurescript +試劑問題

[英]clojurescript + reagent issue

我正在使用clojurescript和試劑制作一個簡單的網絡應用程序。 我想創建一個簡單的“tab”組件,它將包含(對於初學者)文本輸入組件。

該應用程序有2個選項卡,用戶可以選擇選項卡,我想“保留”這兩個選項卡中的每個選項卡中的值。

這是代碼:

(defn atom-input [value]
  [:input {:type "text"
           :value @value
           :on-change #(reset! value (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom 0)]
    (fn []
    [:div
     [:h4 (str "index: " @index)]
     [atom-input a]])))

(defn main-page []
  (let [index (atom 0)]
    [:div.container
     [:div.row
      [:button {:on-click (fn [] (reset! index 0))} "select tab 1"]
      [:button {:on-click (fn [] (reset! index 1))} "select tab 2"]]
     [:div.row
      [simple-tab index]]]))

(defn ^:export run []
  (reagent/render-component
   (fn [] [main-page])
   (.-body js/document)))

問題是,當我切換標簽時,組件共享輸入字段的值 - 我在這里做錯了什么?

非常感謝你的幫助!

問題是你將a (atom 0)傳遞給atom-input控件: [atom-input a] 這導致您的選項卡之間共享相同的原子值。

如果您不想共享該值,則需要將a更改為map: a (atom {})並將地圖和索引傳遞給atom-input ,例如:

(defn atom-input [value index]
  [:input {:type "text"
           :value (or (get @value index) "")
           :on-change #(swap! value assoc index (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom {})]
    (fn []
      [:div
       [:h4 (str "index: " @index)]
       [atom-input a @index]])))

一個更好的方法,恕我直言,是使用游標,所以你不需要將索引和整個地圖傳遞給atom-input ,例如:

(defn atom-input [value]
  [:input {:type "text"
           :value (or @value "")
           :on-change #(reset! value (-> % .-target .-value))}])

(defn simple-tab [index]
  (let [pg-index (atom 1)
        a (atom {})]
    (fn []
      [:div
       [:h4 (str "index: " @index)]
       [atom-input (reagent/cursor [@index] a)]])))

我認為這里存在一些問題,因為您正在混合應用程序數據(狀態)和顯示邏輯數據(即DOM)。 如果你保持兩個不同的東西,即在一個原子中保持你的應用程序狀態,在另一個原子中保持與組件顯示相關的數據,那么事情可能會更清晰。

您的簡單選項卡組件不需要了解選項卡狀態。 它只需要知道應用程序狀態,即通過atom-input輸入/存儲的值。 因此,不是傳遞索引,而是將它傳遞給您想要使用的原子。 這將需要一些更高級別的邏輯來確定呼叫。 例如,如果你有很多標簽,你可能會有類似的東西

(condp = @index
  0 [simple-tab tab0-atom]
  1 [simple-tab tab1-atom]
  ...
  n [simple-tab tabn-atom])

或者你可以修改simple-tab,以便傳入的值,即索引值被用作app-state的一個鍵 - 我認為游標最簡單,即

(def app-state (r/atom {:tabs {0 nil 1 nil}}})

(defn simple-tab [index]
  (let [val-cur (r/cursor app-state [:tabs index])]
    [atom-input val-cur]))

您正在使用form-2組件,即返回函數的組件。

更多細節: https//github.com/Day8/re-frame/wiki/Creating-Reagent-Components#form-2--a-function-returning-a-function

這樣做時,只調用返回的函數,因此你的atom-inputs共享同一個原子。

此外,您應該在內部函數中使用相同的參數

 (defn simple-tab [index]
      (let [pg-index (atom 1)
            a (atom {})]
        (fn [index]
          [:div
           [:h4 (str "index: " @index)]
           [atom-input a @index]])))

在你的情況下,你傳遞一個原子,所以這並不重要,但如果你忘了這個,你將來可能會有錯誤。

關於更廣泛的架構,我建議你使用一個全局原子。 嘗試在這個原子中盡可能多地保持狀態並避免組件本地狀態,這樣更容易推理。

您還可以將選項卡命名為:product:users,並使用multimethod根據所選標簽呈現正確的選項卡。 這樣更容易閱讀,並且將來更容易添加新標簽。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM