Make render force already mounted components to update by default

This should make using Reagent with figwheel more convenient (no need
for force-update-all). Add a fourth argument to render that controls
the updating.
This commit is contained in:
Dan Holmsand 2014-12-07 10:00:47 +01:00
parent 0215a4a093
commit ed06312eaf
4 changed files with 51 additions and 38 deletions

View File

@ -3,6 +3,8 @@
## Upcoming
- `render` now forces a deep update of all components by default, to make it more convenient to use with e.g. figwheel.
- Renamed `as-component` to `as-element`, to match React's new terminology better (old name still works, though, for backward compatiblity).
- Stop wrapping native components. This reduces the number of components created a lot, and can speed some things up substantially (especially render-to-string, that is not bound by browser performance). This is made possible by a new way of keeping track of which order to re-render dirty components.

17
env/dev/devsetup.cljs vendored
View File

@ -4,15 +4,20 @@
[reagent.core :as r]
[figwheel.client :as fw :include-macros true]))
(defn on-update []
(r/force-update-all)
(defn test-results []
[runtests/test-output-mini])
;; (defn on-update []
;; (r/force-update-all)
;; (runtests/run-tests))
(defn start! []
(demo/start! {:test-results test-results})
(runtests/run-tests))
(when r/is-client
(fw/watch-and-reload
:websocket-url "ws://localhost:3449/figwheel-ws"
:jsload-callback #(on-update)))
:jsload-callback #(start!)))
(demo/start! {:test-results (fn []
[runtests/test-output-mini])})
(runtests/run-tests)
(start!)

View File

@ -34,13 +34,19 @@ either a vector (using Reagent's Hiccup syntax), or a React element. The second
Optionally takes a callback that is called when the component is in place.
If the optional fourth argument is true (the default), an already mounted
component will be forced to re-render (by bypassing the default
shouldComponentUpdate).
Returns the mounted component instance."
([comp container]
(render comp container nil))
(render comp container nil true))
([comp container callback]
(render comp container callback true))
([comp container callback force-update]
(let [f (fn []
(as-element (if (fn? comp) (comp) comp)))]
(util/render-component f container callback))))
(util/render-component f container callback force-update))))
(defn unmount-component-at-node
"Remove a component from the given DOM node."

View File

@ -113,7 +113,7 @@
(def react-id-name "data-reactid")
(defn get-react-node [cont]
(when-not (nil? cont)
(when (some? cont)
(if (== doc-node-type (.' cont :nodeType))
(.' cont :documentElement)
(.' cont :firstChild))))
@ -122,42 +122,42 @@
(some-> (get-react-node cont)
(.' getAttribute react-id-name)))
(def roots (atom {}))
(defonce roots (atom {}))
(defn clear-container [node]
;; If render throws, React may get confused, and throw on
;; unmount as well, so try to force React to start over.
(try
(.' js/React unmountComponentAtNode node)
(catch js/Object e
(log e)))
(when-let [n (get-react-node node)]
(.' n removeAttribute react-id-name)
(.! n :innerHTML "")))
(defn render-component [comp container callback force-update]
(try
(binding [*always-update* force-update]
(.' js/React render (comp) container
(fn []
(binding [*always-update* false]
(swap! roots assoc container [comp container])
(if (some? callback)
(callback))))))
(catch js/Object e
(do (clear-container container)
(throw e)))))
(defn re-render-component [comp container]
(try
(.' js/React render (comp) container)
(catch js/Object e
(do
(try
(.' js/React unmountComponentAtNode container)
(catch js/Object e
(log e)))
(when-let [n (get-react-node container)]
(.' n removeAttribute react-id-name)
(.! n :innerHTML ""))
(throw e)))))
(defn render-component [comp container callback]
(.' js/React render (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)))))
(render-component comp container nil true))
(defn unmount-component-at-node [container]
(let [id (get-root-id container)]
(when-not (nil? id)
(swap! roots dissoc id)))
(swap! roots dissoc container)
(.' js/React unmountComponentAtNode container))
(defn force-update-all []
(binding [*always-update* true]
(doseq [f (vals @roots)]
(f)))
(doseq [v (vals @roots)]
(apply re-render-component v))
"Updated")