Обновление состояния приложения Om-Next из удаленного ответа

Я немного озадачен обновлением состояния приложения с удаленного компьютера. Я сделал имитированный пульт, который после некоторой задержки отвечает на модифицированный код с https://github.com/omcljs/om/wiki/Components,-Identity-&-Normalization. Я просто поставил случайные значения для возраста и очков и назвал (cb (rewrite ...)), Но вид не обновляется, хотя :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 мутатор изменен на учебник.

Конечно, у меня неверные ожидания относительно обновлений состояния приложения. Я видел наблюдения за атомами в коде om-next и думал, что изменения ключей, на которые указывает отступ, поставят компоненты в очередь для повторного рендеринга. Это явно не так. Как я могу узнать, что обновления, поступающие с пульта, будут отображаться?

0 ответов

Другие вопросы по тегам