Om ref cursor 在更新时不是 re-rendering 组件
Om ref cursor not re-rendering components when updated
(ns ^:figwheel-always refs-test.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[sablono.core :as html :refer-macros [html]]))
(enable-console-print!)
(def app-state
(atom {:items [{:text "cat"}
{:text "dog"}
{:text "bird"}]
:selected-item {}}))
(defn selected-item []
(om/ref-cursor (:selected-item (om/root-cursor app-state))))
(defn
selected-item-title
[_ owner]
(reify
om/IRender
(render [_]
(html
[:div
(let [selected (om/observe owner (selected-item))]
(if (empty? selected)
[:h1 "Nothing selected"]
[:h1 (:text selected)]))]))))
(defn
selected-item-button
[item owner]
(reify
om/IRender
(render [_]
(html
[:li
[:button {:on-click
(fn []
(om/update! (om/root-cursor app-state) :selected-item item) ;; this doesn't update
;;(om/update! (om/root-cursor app-state) :selected-item (merge item {:foo 1})) ;; this does
)} (:text item)]]))))
(defn
root
[cursor owner]
(reify
om/IRender
(render [_]
(html
[:div
(om/build selected-item-title {})
[:ul
(om/build-all selected-item-button (:items cursor))]]))))
(om/root root app-state
{:target (.getElementById js/document "app")})
(https://www.refheap.com/108491)
(selected-item)
函数创建了一个 ref-cursor,它跟踪 app-state
中的 :selected-item
键。当您单击 selected-item-button
时,标题会更改以反映已放入地图中的新值。但是,这只有效一次。按不同的按钮不会导致标题再次 re-render,因此标题始终停留在您按下的第一个按钮的值上。
虽然,简单地添加一个 merge
和一个额外的关键字似乎可以让它工作......(与空地图合并也不起作用,试过!)
我对引用游标的理解有误吗?
所以,问题很简单。
(om/update! (om/root-cursor app-state) :selected-item item)
应该是
(om/update! (om/root-cursor app-state) :selected-item @item)
请注意该项目,因为它是一个游标,所以被取消引用。
(ns ^:figwheel-always refs-test.core
(:require [om.core :as om :include-macros true]
[om.dom :as dom :include-macros true]
[sablono.core :as html :refer-macros [html]]))
(enable-console-print!)
(def app-state
(atom {:items [{:text "cat"}
{:text "dog"}
{:text "bird"}]
:selected-item {}}))
(defn selected-item []
(om/ref-cursor (:selected-item (om/root-cursor app-state))))
(defn
selected-item-title
[_ owner]
(reify
om/IRender
(render [_]
(html
[:div
(let [selected (om/observe owner (selected-item))]
(if (empty? selected)
[:h1 "Nothing selected"]
[:h1 (:text selected)]))]))))
(defn
selected-item-button
[item owner]
(reify
om/IRender
(render [_]
(html
[:li
[:button {:on-click
(fn []
(om/update! (om/root-cursor app-state) :selected-item item) ;; this doesn't update
;;(om/update! (om/root-cursor app-state) :selected-item (merge item {:foo 1})) ;; this does
)} (:text item)]]))))
(defn
root
[cursor owner]
(reify
om/IRender
(render [_]
(html
[:div
(om/build selected-item-title {})
[:ul
(om/build-all selected-item-button (:items cursor))]]))))
(om/root root app-state
{:target (.getElementById js/document "app")})
(https://www.refheap.com/108491)
(selected-item)
函数创建了一个 ref-cursor,它跟踪 app-state
中的 :selected-item
键。当您单击 selected-item-button
时,标题会更改以反映已放入地图中的新值。但是,这只有效一次。按不同的按钮不会导致标题再次 re-render,因此标题始终停留在您按下的第一个按钮的值上。
虽然,简单地添加一个 merge
和一个额外的关键字似乎可以让它工作......(与空地图合并也不起作用,试过!)
我对引用游标的理解有误吗?
所以,问题很简单。
(om/update! (om/root-cursor app-state) :selected-item item)
应该是
(om/update! (om/root-cursor app-state) :selected-item @item)
请注意该项目,因为它是一个游标,所以被取消引用。