2015-02-21 12 views
8

Próbuję zbudować aplikację Hello World z odczynnikiem/reakcją. Łączę dane wejściowe z atomem przy użyciu kombinacji: :value/:on-change. Jednak, kiedy typ, wejście pozostaje pusta:Wprowadzanie odczynnika nie jest aktualizowane

(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)) 

Gdybym przesunąć atom z let, to będzie działać:

; 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))) 
      }]]) 

Czy dlatego, że v będą redeclared każdorazowo React re -renders? Jeśli tak, w jaki sposób mogę ten kod skorygować, więc nie muszę używać zmiennej globalnej do przechowywania v?

Odpowiedz

5

Okazało się, że to całkiem proste - funkcja "komponentu" może zwrócić nie szablon, ale szablon zwracający funkcję. W ten sposób funkcja zewnętrzna zostanie wykonana tylko raz (i możemy umieścić let tam), a wewnętrzna zostanie wykonany na każdym re-render:

(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

Rozwiązanie to nigdy nie pracował dla mnie aż zmieniłem ': value' do ': defaultValue'. –

Powiązane problemy