Last active
August 29, 2015 14:08
-
-
Save mrcslws/ed7d78d433674c5ab08f to your computer and use it in GitHub Desktop.
Demonstration that Om cursors can quietly dereference to someone else's path. If you quickly move your mouse over this list of names, the assert fails, because you switch up the app-state indices and then cause another event before a render updates the paths.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns explore-om.stalecursors | |
(:require-macros [cljs.core.async.macros :refer [go-loop]]) | |
(:require [om.core :as om :include-macros true] | |
[om.dom :as dom :include-macros true] | |
[cljs.core.async :refer [put! chan <!]])) | |
;;; | |
;;; Sample code from https://github.com/swannodette/om/wiki/Basic-Tutorial | |
;;; | |
(def app-state | |
(atom | |
{:contacts | |
[{:first "Ben" :last "Bitdiddle" | |
:email "[email protected]"} | |
{:first "Alyssa" :middle-initial "P" :last "Hacker" | |
:email "[email protected]"} | |
{:first "Eva" :middle "Lu" :last "Ator" | |
:email "[email protected]"} | |
{:first "Louis" :last "Reasoner" | |
:email "[email protected]"} | |
{:first "Cy" :middle-initial "D" :last "Effect" | |
:email "[email protected]"} | |
{:first "Lem" :middle-initial "E" :last "Tweakit" | |
:email "[email protected]"}]})) | |
(defn middle-name [{:keys [middle middle-initial]}] | |
(cond | |
middle (str " " middle) | |
middle-initial (str " " middle-initial "."))) | |
(defn display-name [{:keys [first last] :as contact}] | |
(str last ", " first (middle-name contact))) | |
;;; | |
;;; When you move the mouse over a contact, have it "flee". | |
;;; Also, sanity-check that the cursor is returning the contact | |
;;; that it's supposed to be referring to. | |
;;; | |
(defn contact-view [contact owner] | |
(reify | |
om/IRenderState | |
(render-state [_ {:keys [flee]}] | |
(let [firstname (:first contact)] | |
(dom/li nil | |
(dom/span | |
#js {:onMouseMove | |
(fn [] | |
(assert (= firstname (:first @contact)) | |
(str "Expected: " firstname | |
" Actual: " (:first @contact))) | |
(put! flee @contact))} | |
(display-name contact)) | |
(dom/button nil "These") | |
(dom/button nil "buttons") | |
(dom/button nil "make") | |
(dom/button nil "the") | |
(dom/button nil "repro") | |
(dom/button nil "more") | |
(dom/button nil "reliable.")))))) | |
;;; | |
;;; When a contact flees, move it to the end of the list. | |
;;; | |
(defn contacts-view [app owner] | |
(reify | |
om/IInitState | |
(init-state [_] | |
{:flee (chan)}) | |
om/IWillMount | |
(will-mount [_] | |
(let [flee (om/get-state owner :flee)] | |
(go-loop [] | |
(let [contact (<! flee)] | |
(om/transact! app :contacts | |
(fn [xs] (conj (vec (remove #(= contact %) xs)) | |
contact)))) | |
(recur)))) | |
om/IRenderState | |
(render-state [this state] | |
(dom/div nil | |
(dom/h2 nil "Contact list") | |
(apply dom/ul nil | |
(om/build-all contact-view (:contacts app) | |
{:init-state state})))))) | |
(defn main [] | |
(om/root contacts-view app-state | |
{:target (. js/document (getElementById "contacts"))})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment