diff --git a/demo/reagentdemo/news/async.cljs b/demo/reagentdemo/news/async.cljs index c27f7b2..8985350 100644 --- a/demo/reagentdemo/news/async.cljs +++ b/demo/reagentdemo/news/async.cljs @@ -38,9 +38,9 @@ tweak #(-> % (+ (rnd)) (/ 2) js/Math.floor)] {:red (tweak red) :green (tweak green) :blue (tweak blue)})) -(defn reset-random-colors [] +(defn reset-random-colors [color] (reset! random-colors - (repeatedly #(-> @base-color tweak-color to-rgb)))) + (repeatedly #(-> color tweak-color to-rgb)))) (defn color-choose [{color-part :color-part}] [:div.color-slider @@ -50,7 +50,7 @@ :on-change (fn [e] (swap! base-color assoc color-part (-> e .-target .-value int)) - (reset-random-colors))}]]) + (reset-random-colors @base-color))}]]) (defn ncolors-choose [] [:div.color-slider @@ -77,7 +77,7 @@ (take n @random-colors))]])) (defn color-demo [] - (reset-random-colors) + (reset-random-colors @base-color) (fn [] [:div [:h2 "Matching colors"] diff --git a/demo/reagentdemo/page.cljs b/demo/reagentdemo/page.cljs index 69c81e9..e6cac92 100644 --- a/demo/reagentdemo/page.cljs +++ b/demo/reagentdemo/page.cljs @@ -85,11 +85,10 @@ ;; First title on a page wins (reset! title-atom ""))) -(defn title [props children] - (let [name (first children)] - (when (= @title-atom "") - (if reagent/is-client - (let [title (aget (.getElementsByTagName js/document "title") 0)] - (set! (.-innerHTML title) name))) - (reset! title-atom name)) - [:div])) +(defn title [name] + (when (= @title-atom "") + (if reagent/is-client + (let [title (aget (.getElementsByTagName js/document "title") 0)] + (set! (.-innerHTML title) name))) + (reset! title-atom name)) + [:div]) diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index b0149b2..6107e61 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -54,7 +54,6 @@ (defn do-render [C] - (set! (.-cljsIsDirty C) false) (binding [*current-component* C] (let [f (aget C cljs-render) _ (assert (fn? f)) @@ -124,10 +123,7 @@ :componentWillUnmount (fn [] (this-as C - (let [ratom (.-cljsRatom C)] - (if-not (nil? ratom) - (ratom/dispose! ratom))) - (set! (.-cljsIsDirty C) false) + (util/dispose C) (when f (f C)))) nil)) @@ -166,8 +162,7 @@ :render (if util/isClient (fn [] (this-as C - (util/run-reactively - C #(do-render C) #(util/queue-render C)))) + (util/run-reactively C #(do-render C)))) (fn [] (this-as C (do-render C)))))) (defn wrap-funs [fun-map] diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 273b00b..7446eff 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -3,10 +3,14 @@ (:require [clojure.string :as string] [reagent.impl.reactimport :as reactimport] [reagent.impl.util :as util :refer [cljs-level]] + [reagent.ratom :as ratom] [reagent.debug :refer-macros [dbg prn println log]])) (def React reactimport/React) +(def debug false) +(assert (set! debug true)) + (def cljs-argv "cljsArgv") (def isClient util/isClient) @@ -148,7 +152,8 @@ (defn wrap-component [comp extras name] (let [def #js {:render - #(this-as C (wrapped-render C comp extras)) + (fn [] + (this-as C (wrapped-render C comp extras))) :shouldComponentUpdate #(this-as C (wrapped-should-update C %1 %2)) :displayName (or name "ComponentWrapper")}] @@ -216,9 +221,27 @@ (aset jsprops "key" key)))) (c jsprops))) +(def tmp #js {}) + +(defn warn-on-deref [x] + (when-not (.-warned tmp) + (log "Warning: Reactive deref not supported in seq in " + (pr-str x)) + (set! (.-warned tmp) true))) + +(defn expand-seq [x level] + (map-into-array as-component (inc level) x)) + (defn as-component ([x] (as-component x 0)) ([x level] (cond (vector? x) (vec-to-comp x level) - (seq? x) (map-into-array as-component level x) + (seq? x) (if-not (and debug (nil? ratom/*ratom-context*)) + (expand-seq x level) + (let [s (ratom/capture-derefed + #(expand-seq x level) + tmp)] + (when (ratom/captured tmp) + (warn-on-deref x)) + s)) true x))) diff --git a/src/reagent/impl/util.cljs b/src/reagent/impl/util.cljs index 07a0198..d90d834 100644 --- a/src/reagent/impl/util.cljs +++ b/src/reagent/impl/util.cljs @@ -1,6 +1,6 @@ (ns reagent.impl.util (:refer-clojure :exclude [flush]) - (:require [reagent.debug :refer-macros [dbg]] + (:require [reagent.debug :refer-macros [dbg log]] [reagent.ratom :as ratom])) (def isClient (not (nil? (try (.-document js/window) @@ -61,6 +61,35 @@ (.queue-render render-queue C)) +;; Render helper + +(defn is-reagent-component [C] + (and (not (nil? C)) + (aget C "props") + (-> C (aget "props") (aget "cljsArgv")))) + +(defn run-reactively [C run] + (assert (is-reagent-component C)) + (set! (.-cljsIsDirty C) false) + (let [rat (.-cljsRatom C)] + (if (nil? rat) + (let [res (ratom/capture-derefed run C) + derefed (ratom/captured C)] + (when (not (nil? derefed)) + (set! (.-cljsRatom C) + (ratom/make-reaction run + :auto-run #(queue-render C) + :derefed derefed))) + res) + (ratom/run rat)))) + +(defn dispose [C] + (let [ratom (.-cljsRatom C)] + (if-not (nil? ratom) + (ratom/dispose! ratom))) + (set! (.-cljsIsDirty C) false)) + + ;; Misc utilities (deftype partial-ifn [f args ^:mutable p] @@ -136,20 +165,3 @@ (shallow-equal-maps (v1 1) (v2 1)))) (recur (inc n)) false))))))) - - -;; Render helper - -(defn run-reactively [C run on-dirty] - (let [rat (.-cljsRatom C)] - (if (nil? rat) - (let [res (ratom/capture-derefed run C) - derefed (.-captured C)] - (when (not (nil? derefed)) - (set! (.-cljsRatom C) - (ratom/make-reaction run - :auto-run on-dirty - :derefed derefed))) - res) - (ratom/run rat)))) - diff --git a/src/reagent/ratom.cljs b/src/reagent/ratom.cljs index 225bcc5..9742394 100644 --- a/src/reagent/ratom.cljs +++ b/src/reagent/ratom.cljs @@ -15,6 +15,11 @@ (binding [*ratom-context* obj] (f))) +(defn captured [obj] + (let [c (.-captured obj)] + (set! (.-captured obj) nil) + c)) + (defn- notify-deref-watcher! [derefable] (let [obj *ratom-context*] (when-not (nil? obj) diff --git a/test/testcloact.cljs b/test/testcloact.cljs index 84b8eb8..9a572c1 100644 --- a/test/testcloact.cljs +++ b/test/testcloact.cljs @@ -219,7 +219,7 @@ (when isClient (let [ran (atom 0) state (atom 0) - really-simple (fn [props children this] + really-simple (fn [] (swap! ran inc) (if (= @state 1) (reset! state 3))