2015-02-21 19 views
8

Reaktif/Tepkime ile bir Hello World uygulaması oluşturmaya çalışıyorum. :value/:on-change combo kullanarak bir giriş ile bir giriş bağladım. Ben yazarken Ancak, giriş boş kalır: Ben let dışına atomu taşırsanızReaktif girişi güncellenmiyor

(defn new-user [] 
    ; Atom declared in an inner `let`. 
    (let [v (atom "")] 
    [:div 
    [:input {:type "text" 
       :value @v 
       :on-change (fn [evt] 
          (reset! v (-> evt .-target .-value))) 
       }]])) 

(defn app [state] 
    [:div 
    [:p "State" (pr-str @app-state)] 
    [new-user]]) 

(r/render-component [app app-state] 
        (.-body js/document)) 

, işe yarayacak: v her seferinde yeniden Tepki redeclared çünkü

; Atom is now top-level. 
(defonce v (atom "")) 

(defn new-user [] 
    [:div 
    [:input {:type "text" 
      :value @v 
      :on-change (fn [evt] 
         (reset! v (-> evt .-target .-value))) 
      }]]) 

bunu mı -renders? Eğer öyleyse, bu kodu nasıl yeniden gözden geçiririm? Böylece global değişkeni v tutmak için kullanmam gerekmez mi?

cevap

5

Oldukça kolay olduğu ortaya çıktı - "bileşen" işlevi bir şablonu değil, bir işlevi döndüren bir işlevi döndürebilir. Dış fonksiyonu (ve orada let koyabilirsiniz) sadece bir kez çalıştırılacaktır ve iç her çalıştırılacak Bu şekilde yeniden işlemek:

(defn new-user [] 
    (let [v (atom "")] 
    ; The returned function will be called on every re-render. 
    (fn [] 
     [:div 
     [:input {:type "text" 
       :value @v 
       :on-change (fn [evt] 
          (reset! v (-> evt .-target .-value)))}]]))) 
+3

benim değiştiğimi kadar benim için hiç çalışmamış Bu çözüm: value' için ': defaultValue'. –