diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index 0390cd0..84962c9 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -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: diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 0a0374b..3be4da9 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -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] diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 4cc5e13..ef01140 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -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 diff --git a/src/reagent/impl/util.cljs b/src/reagent/impl/util.cljs index d06d477..db7f394 100644 --- a/src/reagent/impl/util.cljs +++ b/src/reagent/impl/util.cljs @@ -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)) diff --git a/test/runtests.cljs b/test/runtests.cljs index 33db49a..8674360 100644 --- a/test/runtests.cljs +++ b/test/runtests.cljs @@ -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))