2016-05-13 52 views
5

這似乎並不被髮生的Quick Start tutorial說:爲什麼Om Next組件在狀態更改時不重新呈現?

在庵下一個應用程序狀態的變化是由調解管理。協調器接受新穎性,將其合併到應用程序狀態中, 根據其聲明的查詢找到所有受影響的組件,並且 計劃重新呈現。

當我改變選擇框時,mutate函數更新狀態,但App組件的render函數從不執行。我可以在REPL中看到@ app-state狀態已經改變,我從來沒有在應用程序的渲染函數中看到控制檯中prn的輸出。這是我在控制檯中看到:

[1955.847s] [om.next] transacted '[(om-tutorial.core/switch-topic {:name "b"})], #uuid "c3ba6741-81ea-4cbb-8db1-e86eec26b540" 
"read :default" :topics 

如果我(swap! app-state update-in [:current-topic] (fn [] "b"))更新從REPL狀態則APP的渲染功能無法執行。這裏是控制檯輸出:

"read :default" :topics 
"read :default" :current-topic 
"App om-props " {:topics [{:name "a"} {:name "b"}], :current-topic "b"} 
"Topics om-props " {:topics [{:name "a"} {:name "b"}]} 

下面是完整的代碼:

(ns om-tutorial.core 
    (:require [goog.dom :as gdom] 
      [om.next :as om :refer-macros [defui]] 
      [om.dom :as dom])) 

(enable-console-print!) 

(def app-state (atom {:current-topic "a" :topics [{:name "a"} {:name "b"}]})) 

(defmulti read (fn [env key params] key)) 

(defmethod read :default 
    [{:keys [state] :as env} key params] 
    (prn "read :default" key) 
    (let [st @state] 
    (if-let [value (st key)] 
     {:value value} 
     {:value :not-found}))) 

(defmulti mutate om/dispatch) 

(defmethod mutate 'om-tutorial.core/switch-topic 
    [{:keys [state]} _ {:keys [name]}] 
    {:action 
    (fn [] 
    (swap! state update-in 
     [:current-topic] 
     #(identity name)))}) 

(defui Topics 
    static om/IQuery 
    (query [this] 
     [:topics]) 
    Object 
    (render [this] 
      (let [{:keys [topics] :as props} (om/props this)] 
      (prn "Topics om-props " props) 
      (apply dom/select #js {:id "topics" 
            :onChange 
            (fn [e] 
            (om/transact! this 
                `[(switch-topic ~{:name (.. e -target -value)})]))} 
        (map #(dom/option nil (:name %)) topics))))) 

(def topics-view (om/factory Topics)) 

(defui App 
    static om/IQuery 
    (query [this] 
     '[:topics :current-topic]) 
    Object 
    (render [this] 
      (let [{:keys [topics current-topic] :as om-props} (om/props this)] 
      (prn "App om-props " om-props) 
      (dom/div nil 
        (topics-view {:topics topics}) 
        (dom/h3 nil current-topic))))) 

(def reconciler 
    (om/reconciler 
    {:state app-state 
    :parser (om/parser {:read read :mutate mutate})})) 


(om/add-root! reconciler App (gdom/getElement "app")) 

這裏是project.clj文件:

(defproject om-tutorial "0.1.0-SNAPSHOT" 
    :description "My first Om program!" 
    :dependencies [[org.clojure/clojure "1.7.0"] 
       [org.clojure/clojurescript "1.7.170"] 
       [org.omcljs/om "1.0.0-alpha24"] 
       [figwheel-sidecar "0.5.0-SNAPSHOT" :scope "test"]]) 

回答

1

我有同樣的問題在我的應用程序和找到了解決方法(儘管這可能不是最好的解決方案)。您可以通過傳遞父組件的om屬性來構建組件。

你的UI應用程序可能會再看看這樣的:

(defui App 
    Object 
    (render [this] 
      (dom/div nil (topics-view (om/props this))))) 

IQuery絕對是更好的解決方案,但我仍然有同樣的問題,像你這樣的。這種解決方法現在在我的項目中運行,我一定會再次看看IQuery

編輯

本教程大約Components, Identity and Normalization說明你要做的時候才需要更新UI的東西。這導致了更習慣的解決方案。

0

Om爲了避免不必要地調用讀取函數並避免無用的重新呈現,接下來不願意爲了性能原因觸發重新讀取查詢。

(om/transact! this 
    `[(switch-topic ~{:name (.. e -target -value)}) 
    :current-topic]) 

參考:https://github.com/omcljs/om/wiki/Documentation-(om.next)#transact

要指定該查詢 :current-topic組件應該重新渲染(並呼籲相關的讀取功能),可以在辦理向量的末尾提供這些鍵
相關問題