Re-render components in mount order instead of tree depth

This should be more robust, and allows us to stop passing tree
levels along to every component.
This commit is contained in:
Dan Holmsand 2014-11-22 12:36:36 +01:00
parent 6b87349d88
commit a1c6990c18
3 changed files with 43 additions and 34 deletions

View File

@ -8,6 +8,11 @@
;;; Update batching
(defonce mount-count #js {:count 0})
(defn next-mount-count []
(.! mount-count :count (inc (.' mount-count :count))))
(defn fake-raf [f]
(js/setTimeout f 16))
@ -21,14 +26,14 @@
(.' w :msRequestAnimationFrame)
fake-raf))))
(defn compare-levels [c1 c2]
(- (.' c1 :props.level)
(.' c2 :props.level)))
(defn compare-mount-order [c1 c2]
(- (.' c2 :cljsMountOrder)
(.' c1 :cljsMountOrder)))
(defn run-queue [a]
;; sort components by level, to make sure parents
;; sort components by mount order, to make sure parents
;; are rendered before children
(.sort a compare-levels)
(.sort a compare-mount-order)
(dotimes [i (alength a)]
(let [c (aget a i)]
(when (.' c :cljsIsDirty)

View File

@ -49,7 +49,7 @@
5 (f (nth argv 1) (nth argv 2) (nth argv 3) (nth argv 4))
(apply f (subvec argv 1)))))]
(if (vector? res)
(.' c asComponent res (.' p :level))
(.' c asComponent res)
(if (ifn? res)
(do
(.! c :cljsRender res)
@ -96,6 +96,13 @@
(this-as c
(f c (.' oldprops :argv))))
:componentDidMount
(fn []
(this-as c
(.! c :cljsMountOrder (batch/next-mount-count))
(when-not (nil? f)
(f c))))
:componentWillUnmount
(fn []
(this-as c
@ -129,6 +136,7 @@
(or wrap (default-wrapper f)))))
(def obligatory {:shouldComponentUpdate nil
:componentDidMount nil
:componentWillUnmount nil})
(def dash-to-camel (util/memoize-1 util/dash-to-camel))

View File

@ -143,8 +143,7 @@
(when-not (nil? input-setup)
(input-setup this jsprops))
(make-element argv comp jsprops
(if hasprops 2 1)
(inc (.' inprops :level)))))
(if hasprops 2 1))))
(defn wrapped-should-update [c nextprops nextstate]
(or util/*always-update*
@ -209,13 +208,12 @@
(defn get-key [x]
(when (map? x) (get x :key)))
(defn vec-to-comp [v level]
(defn vec-to-comp [v]
(assert (pos? (count v)) "Hiccup form should not be empty")
(assert (valid-tag? (nth v 0))
(str "Invalid Hiccup form: " (pr-str v)))
(let [c (as-class (nth v 0))
jsprops #js{:argv v
:level level}]
jsprops #js{:argv v}]
(let [k (-> v meta get-key)
k' (if (nil? k)
(-> v (nth 1 nil) get-key)
@ -235,40 +233,38 @@
(declare expand-seq)
(defn as-component
([x] (as-component x 0))
([x level]
[x]
(cond (string? x) x
(vector? x) (vec-to-comp x level)
(vector? x) (vec-to-comp x)
(seq? x) (if (dev?)
(if (nil? ratom/*ratom-context*)
(expand-seq x level)
(expand-seq x)
(let [s (ratom/capture-derefed
#(expand-seq x level)
#(expand-seq x)
seq-ctx)]
(when (ratom/captured seq-ctx)
(warn-on-deref x))
s))
(expand-seq x level))
true x)))
(expand-seq x))
true x))
(defn create-class [spec]
(comp/create-class spec as-component))
(defn expand-seq [s level]
(let [a (into-array s)
level' (inc level)]
(defn expand-seq [s]
(let [a (into-array s)]
(dotimes [i (alength a)]
(aset a i (as-component (aget a i) level')))
(aset a i (as-component (aget a i))))
a))
(defn make-element [argv comp jsprops first-child level]
(defn make-element [argv comp jsprops first-child]
(if (== (count argv) (inc first-child))
;; Optimize common case of one child
(.' js/React createElement comp jsprops
(as-component (nth argv first-child) level))
(as-component (nth argv first-child)))
(.apply (.' js/React :createElement) nil
(reduce-kv (fn [a k v]
(when (>= k first-child)
(.push a (as-component v level)))
(.push a (as-component v)))
a)
#js[comp jsprops] argv))))