2015-02-21 27 views
8

Ich versuche eine Hello World App mit Reagent/React zu erstellen. Ich binde einen Eingang mit einem Atom mit :value/:on-change Combo. Allerdings, wenn ich schreibe, bleibt der Eingang leer:Reagenzeingang wird nicht aktualisiert

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

Wenn ich das Atom aus let bewegen, wird es funktionieren:

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

es ist, weil die v wird jedes Mal reagieren re neu deklariert werden -Render? Wenn ja, wie reformiere ich diesen Code, so dass ich keine globale Variable verwenden muss, um v zu halten?

Antwort

5

Ich stellte sich heraus, ziemlich einfach zu sein - die "Komponente" -Funktion kann nicht eine Vorlage, sondern eine Funktion zurückgeben Vorlage. Auf diese Weise die äußere Funktion nur einmal ausgeführt werden (und wir können let dort gesetzt) ​​und Innen werden an jedem ausgeführt werden wieder machen:

(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

Diese Lösung nie für mich gearbeitet, bis ich 'geändert: value' zu ': defaultValue'. –