diff --git a/CHANGELOG.md b/CHANGELOG.md index 545488a..1d18435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/env/dev/devsetup.cljs b/env/dev/devsetup.cljs index f9e8d46..695e3f9 100644 --- a/env/dev/devsetup.cljs +++ b/env/dev/devsetup.cljs @@ -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!) diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index d42050a..c469426 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -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." diff --git a/src/reagent/impl/util.cljs b/src/reagent/impl/util.cljs index 3ece7ff..7939f21 100644 --- a/src/reagent/impl/util.cljs +++ b/src/reagent/impl/util.cljs @@ -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")