Add force-update-all, to make LightTable integration easier

force-update-all re-mounts all root components, and makes all
their children re-render.
This commit is contained in:
Dan Holmsand 2014-03-18 13:09:55 +01:00
parent 82a1dd73eb
commit ba995c2e0d
5 changed files with 78 additions and 17 deletions

View File

@ -28,19 +28,21 @@ Returns the mounted component instance."
([comp container]
(render-component comp container nil))
([comp container callback]
(odo React :renderComponent
(as-component comp) container callback)))
(util/render-component (as-component comp) container callback)))
(defn unmount-component-at-node
"Remove a component from the given DOM node."
[container]
(odo React :unmountComponentAtNode container))
(util/unmount-component-at-node container))
(defn render-component-to-string
"Turns a component into an HTML string."
([component]
(odo React :renderComponentToString (as-component component))))
(defn ^:export force-update-all []
(util/force-update-all))
(defn create-class
"Create a component, React style. Should be called with a map,
looking like this:

View File

@ -74,14 +74,15 @@
:shouldComponentUpdate
(fn [nextprops nextstate]
(this-as c
;; Don't care about nextstate here, we use forceUpdate
;; when only when state has changed anyway.
(let [old-argv (oget c :props :argv)
new-argv (oget nextprops :argv)]
(if (nil? f)
(not (util/equal-args old-argv new-argv))
(f c old-argv new-argv)))))
(or util/*always-update*
(this-as c
;; Don't care about nextstate here, we use forceUpdate
;; when only when state has changed anyway.
(let [old-argv (oget c :props :argv)
new-argv (oget nextprops :argv)]
(if (nil? f)
(not (util/equal-args old-argv new-argv))
(f c old-argv new-argv))))))
:componentWillUpdate
(fn [nextprops]

View File

@ -140,9 +140,10 @@
(.apply comp nil jsargs)))
(defn wrapped-should-update [c nextprops nextstate]
(let [a1 (oget c :props :argv)
a2 (oget nextprops :argv)]
(not (util/equal-args a1 a2))))
(or util/*always-update*
(let [a1 (oget c :props :argv)
a2 (oget nextprops :argv)]
(not (util/equal-args a1 a2)))))
(defn add-input-methods [spec]
(doto spec

View File

@ -1,5 +1,5 @@
(ns reagent.impl.util
(:require [reagent.debug :refer-macros [dbg]]
(:require [reagent.debug :refer-macros [dbg log]]
[reagent.interop :refer-macros [oget oset odo]]
[clojure.string :as string]))
@ -109,6 +109,60 @@
(merge-style p1 (merge-class p1 (merge p1 p2))))))
(declare ^:dynamic *always-update*)
(def doc-node-type 9)
(def react-id-name "data-reactid")
(defn get-react-node [cont]
(when-not (nil? cont)
(if (== doc-node-type (oget cont :nodeType))
(oget cont :documentElement)
(oget cont :firstChild))))
(defn get-root-id [cont]
(some-> (get-react-node cont)
(odo :getAttribute react-id-name)))
(def roots (atom {}))
(defn re-render-component [comp container]
(try
(odo React :renderComponent comp container)
(catch js/Object e
(do
(try
(odo React :unmountComponentAtNode container)
(catch js/Object e
(log e)))
(when-let [n (get-react-node container)]
(odo n :removeAttribute react-id-name)
(oset n :innerHTML ""))
(throw e)))))
(defn render-component [comp container callback]
(odo React :renderComponent
comp container
(fn []
(let [id (get-root-id container)]
(when-not (nil? id)
(swap! roots assoc id
#(re-render-component comp container))))
(when-not (nil? callback)
(callback)))))
(defn unmount-component-at-node [container]
(let [id (get-root-id container)]
(when-not (nil? id)
(swap! roots dissoc id)))
(odo React :unmountComponentAtNode container))
(defn force-update-all []
(binding [*always-update* true]
(doseq [f (vals @roots)]
(f)))
"Updated")
;;; Helpers for shouldComponentUpdate
(def -not-found (js-obj))

View File

@ -1,6 +1,7 @@
(ns runtests
(:require [reagent.core :as reagent :refer [atom]]
[reagent.interop :refer-macros [oget oset odo]]
[reagent.debug :refer-macros [dbg println]]
[demo :as demo]
[cemerick.cljs.test :as t]))
@ -18,7 +19,7 @@
[:p (str "Ran " (:test res) " tests containing "
(+ (:pass res) (:fail res) (:error res))
" assertions.")]
[:p (:fail res) " failues, " (:error res) " errors."]])]))
[:p (:fail res) " failures, " (:error res) " errors."]])]))
(defn test-output-mini []
(let [res @test-results]
@ -47,5 +48,7 @@
(println "-----------------------------------------"))
(if reagent/is-client
(js/setTimeout run-all-tests 1000)
(do
(reset! test-results nil)
(js/setTimeout run-all-tests 1000))
(run-all-tests))