从远程响应更新Om-Next应用程序状态

时间:2016-04-28 19:26:17

标签: clojurescript om om-next

我对从远程更新app状态感到困惑。我做了一个模拟的遥控器,它在对来自https://github.com/omcljs/om/wiki/Components,-Identity-&-Normalization的修改后的代码有一些延迟后作出响应。我只是为年龄和点数添加随机值,并调用(cb (rewrite ...))。但是虽然ident引用的:person/by-name发生了更改,但视图仍未更新,生成的值仅在下一次交易后呈现。这是更改后的代码:

(ns om-learning.cards.tutorial
  (:require [om.next :as om :refer-macros [defui]]
            [om.dom :as dom])
  (:require-macros [devcards.core :refer [defcard defcard-doc defcard-om-next]]))
​
(enable-console-print!)
​
(def init-data
  {:list/one [{:name "John" :points 0}
              {:name "Mary" :points 0}
              {:name "Bob"  :points 0}]
   :list/two [{:name "Mary" :points 0 :age 27}
              {:name "Gwen" :points 0}
              {:name "Jeff" :points 0}]})
​
;; -----------------------------------------------------------------------------
;; Parsing
​
(defmulti read om/dispatch)
​
(defn get-people [state key]
  (let [st @state
        res (into [] (map #(get-in st %)) (get st key))]
    (println "Key: " key)
    (println "St: " st)
    (println "Res: " res)
    (println "(get st key): " (get st key))
    res
    ))
​
(defmethod read :list/one
  [{:keys [state] :as env} key params]
  (do
    (print "READ state: " @state)
    (print "READ key: " key)
    {:value (get-people state key)}))
​
(defmethod read :list/two
  [{:keys [state] :as env} key params]
  {:value (get-people state key)})
​
(defmulti mutate om/dispatch)
​
(defmethod mutate 'points/increment
  [{:keys [state]} _ {:keys [name]}]
  {:action
   (fn []
     (swap! state update-in
            [:person/by-name name :points]
            inc))
   :remote true})
​
(defmethod mutate 'points/decrement
  [{:keys [state]} _ {:keys [name]}]
  {:action
   (fn []
     (swap! state update-in
            [:person/by-name name :points]
            #(let [n (dec %)] (if (neg? n) 0 n))))})
​
;; -----------------------------------------------------------------------------
;; Components
​
(defui Person
  static om/Ident
  (ident [this {:keys [name]}]
    [:person/by-name name])
  static om/IQuery
  (query [this]
    [:name :points :age])
  Object
  (render [this]
    (println "Render Person" (-> this om/props :name))
    (let [{:keys [points name age] :as props} (om/props this)]
      (dom/li nil
              (dom/label nil (str name ", age: " (or age "?") ", points: " points))
              (dom/button
                #js {:onClick
                     (fn [e]
                       (om/transact! this
                                     `[(points/increment ~props)]))}
                "+")
              (dom/button
                #js {:onClick
                     (fn [e]
                       (om/transact! this
                                     `[(points/decrement ~props)]))}
                "-")))))
​
(def person (om/factory Person {:keyfn :name}))
​
(defui ListView
  Object
  (render [this]
    (println "Render ListView" (-> this om/path first))
    (let [list (om/props this)]
      (apply dom/ul nil
             (map person list)))))
​
(def list-view (om/factory ListView))
​
(defui RootView
  static om/IQuery
  (query [this]
    (let [subquery (om/get-query Person)]
      `[{:list/one ~subquery} {:list/two ~subquery}]))
  Object
  (render [this]
    (println "Render RootView")
    (let [{:keys [list/one list/two]} (om/props this)]
      (apply dom/div nil
             [(dom/h2 nil "List A")
              (list-view one)
              (dom/h2 nil "List B")
              (list-view two)]))))
​
(defn send [{:keys [remote]} cb]
  (let [{:keys [rewrite]} (om/process-roots remote)]
    (js/setTimeout
      (fn []
        (let [next-age (rand-int 100) next-points (rand-int 10)]
          (println "REWRITING age:" next-age "points:" next-points)
          (cb (rewrite
                {:person/by-name
                 (into {}
                       (map (fn [x] [x {:name x :points next-points :age next-age}])
                            ["John" "Mary" "Bob" "Gwen" "Jeff"]))})))
        ) 1500)))
​
(def reconciler
  (om/reconciler
    {:state  init-data
     :parser (om/parser {:read read :mutate mutate})
     :send   send}))
​
(defcard (-> Person om.next/get-query meta))
​
(defcard init-data-card init-data)
​
(defcard
  (om/tree->db RootView init-data true))
​
(defcard-om-next
  root-view
  RootView reconciler)

在该代码中,send函数和points/increment mutator已更改为教程。

我当然对应用状态更新有不正确的期望。我已经在om-next代码中看到了对原子的监视,并认为缩进引用的键的更改会将组件排入队列以重新渲染。显然不是这样。如何才能获得来自遥控器的更新?

0 个答案:

没有答案