Factor out batching logic into own ns

This commit is contained in:
Dan Holmsand 2014-02-11 15:34:06 +01:00
parent c18b8c318e
commit 6eb6b482f5
4 changed files with 96 additions and 87 deletions

View File

@ -5,6 +5,7 @@
(:require [reagent.impl.template :as tmpl]
[reagent.impl.component :as comp]
[reagent.impl.util :as util]
[reagent.impl.batching :as batch]
[reagent.ratom :as ratom]))
(def React util/React)
@ -110,7 +111,7 @@ specially, like React's transferPropsTo."
Note that this may not work in event handlers, since React.js does
batching of updates there."
[]
(util/flush))
(batch/flush))

View File

@ -0,0 +1,88 @@
(ns reagent.impl.batching
(:refer-clojure :exclude [flush])
(:require [reagent.debug :refer-macros [dbg log]]
[reagent.ratom :as ratom]
[reagent.impl.util :refer [cljs-level is-client]]
[clojure.string :as string]))
;;; Update batching
(defn fake-raf [f]
(js/setTimeout f 16))
(def next-tick
(if-not is-client
fake-raf
(let [w js/window]
(or (.-requestAnimationFrame w)
(.-webkitRequestAnimationFrame w)
(.-mozRequestAnimationFrame w)
(.-msRequestAnimationFrame w)
fake-raf))))
(defn compare-levels [c1 c2]
(- (-> c1 (aget "props") (aget cljs-level))
(-> c2 (aget "props") (aget cljs-level))))
(defn run-queue [a]
;; sort components by level, to make sure parents
;; are rendered before children
(.sort a compare-levels)
(dotimes [i (alength a)]
(let [C (aget a i)]
(when (.-cljsIsDirty C)
(.forceUpdate C)))))
(deftype RenderQueue [^:mutable queue ^:mutable scheduled?]
Object
(queue-render [this C]
(.push queue C)
(.schedule this))
(schedule [this]
(when-not scheduled?
(set! scheduled? true)
(next-tick #(.run-queue this))))
(run-queue [_]
(let [q queue]
(set! queue (array))
(set! scheduled? false)
(run-queue q))))
(def render-queue (RenderQueue. (array) false))
(defn flush []
(.run-queue render-queue))
(defn queue-render [C]
(set! (.-cljsIsDirty C) true)
(.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))

View File

@ -1,6 +1,7 @@
(ns reagent.impl.component
(:require [reagent.impl.util :as util :refer [cljs-level cljs-argv React]]
[reagent.impl.batching :as batch]
[reagent.ratom :as ratom]
[reagent.debug :refer-macros [dbg prn]]))
@ -121,7 +122,7 @@
:componentWillUnmount
(fn []
(this-as C
(util/dispose C)
(batch/dispose C)
(when f (f C))))
nil))
@ -150,9 +151,11 @@
(def obligatory {:shouldComponentUpdate nil
:componentWillUnmount nil})
(def dash-to-camel (memoize util/dash-to-camel))
(defn camelify-map-keys [fun-map]
(reduce-kv (fn [m k v]
(assoc m (-> k util/dash-to-camel keyword) v))
(assoc m (-> k dash-to-camel keyword) v))
{} fun-map))
(defn add-obligatory [fun-map]
@ -164,7 +167,7 @@
:render (if util/is-client
(fn []
(this-as C
(util/run-reactively C #(do-render C))))
(batch/run-reactively C #(do-render C))))
(fn [] (this-as C (do-render C))))))
(defn wrap-funs [fun-map]

View File

@ -1,7 +1,5 @@
(ns reagent.impl.util
(:refer-clojure :exclude [flush])
(:require [reagent.debug :refer-macros [dbg log]]
[reagent.ratom :as ratom]
[reagent.impl.reactimport :as reactimport]
[clojure.string :as string]))
@ -12,87 +10,6 @@
(def cljs-argv "cljsArgv")
(def React reactimport/React)
;;; Update batching
(defn fake-raf [f]
(js/setTimeout f 16))
(def next-tick
(if-not is-client
fake-raf
(let [w js/window]
(or (.-requestAnimationFrame w)
(.-webkitRequestAnimationFrame w)
(.-mozRequestAnimationFrame w)
(.-msRequestAnimationFrame w)
fake-raf))))
(defn compare-levels [c1 c2]
(- (-> c1 (aget "props") (aget cljs-level))
(-> c2 (aget "props") (aget cljs-level))))
(defn run-queue [a]
;; sort components by level, to make sure parents
;; are rendered before children
(.sort a compare-levels)
(dotimes [i (alength a)]
(let [C (aget a i)]
(when (.-cljsIsDirty C)
(.forceUpdate C)))))
(deftype RenderQueue [^:mutable queue ^:mutable scheduled?]
Object
(queue-render [this C]
(.push queue C)
(.schedule this))
(schedule [this]
(when-not scheduled?
(set! scheduled? true)
(next-tick #(.run-queue this))))
(run-queue [_]
(let [q queue]
(set! queue (array))
(set! scheduled? false)
(run-queue q))))
(def render-queue (RenderQueue. (array) false))
(defn flush []
(.run-queue render-queue))
(defn queue-render [C]
(set! (.-cljsIsDirty C) true)
(.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