mirror of
https://github.com/status-im/reagent.git
synced 2025-01-14 13:54:08 +00:00
Make sure lifecycle callbacks work when called as native component
This commit is contained in:
parent
fbbc5e72c6
commit
776c47491c
@ -39,13 +39,29 @@
|
|||||||
(props-argv c (.' c :props)))
|
(props-argv c (.' c :props)))
|
||||||
|
|
||||||
(defn get-props [c]
|
(defn get-props [c]
|
||||||
(-> (get-argv c) extract-props))
|
(let [p (.' c :props)]
|
||||||
|
(if-some [v (.' p :argv)]
|
||||||
|
(extract-props v)
|
||||||
|
(shallow-obj-to-map p))))
|
||||||
|
|
||||||
(defn get-children [c]
|
(defn get-children [c]
|
||||||
(-> (get-argv c) extract-children))
|
(let [p (.' c :props)]
|
||||||
|
(if-some [v (.' p :argv)]
|
||||||
|
(extract-children v)
|
||||||
|
(->> (.' p :children)
|
||||||
|
(.' util/react Children.toArray)
|
||||||
|
(into [])))))
|
||||||
|
|
||||||
(defn reagent-component? [c]
|
(defn ^boolean reagent-class? [c]
|
||||||
(-> (get-argv c) nil? not))
|
(and (fn? c)
|
||||||
|
(some? (some-> c .-prototype (.' :reagentRender)))))
|
||||||
|
|
||||||
|
(defn ^boolean react-class? [c]
|
||||||
|
(and (fn? c)
|
||||||
|
(some? (some-> c .-prototype (.' :render)))))
|
||||||
|
|
||||||
|
(defn ^boolean reagent-component? [c]
|
||||||
|
(some? (.' c :reagentRender)))
|
||||||
|
|
||||||
(defn cached-react-class [c]
|
(defn cached-react-class [c]
|
||||||
(.' c :cljsReactClass))
|
(.' c :cljsReactClass))
|
||||||
@ -69,9 +85,6 @@
|
|||||||
|
|
||||||
;;; Rendering
|
;;; Rendering
|
||||||
|
|
||||||
(defn ^boolean reagent-class? [c]
|
|
||||||
(and (fn? c)
|
|
||||||
(some? (some-> c .-prototype (.' :reagentRender)))))
|
|
||||||
|
|
||||||
(defn wrap-render [c]
|
(defn wrap-render [c]
|
||||||
(let [f (.' c :reagentRender)
|
(let [f (.' c :reagentRender)
|
||||||
@ -146,8 +159,8 @@
|
|||||||
(this-as c (reset! (state-atom c) (.call f c c))))
|
(this-as c (reset! (state-atom c) (.call f c c))))
|
||||||
|
|
||||||
:componentWillReceiveProps
|
:componentWillReceiveProps
|
||||||
(fn componentWillReceiveProps [props]
|
(fn componentWillReceiveProps [nextprops]
|
||||||
(this-as c (.call f c c (get-argv c))))
|
(this-as c (.call f c c (props-argv c nextprops))))
|
||||||
|
|
||||||
:shouldComponentUpdate
|
:shouldComponentUpdate
|
||||||
(fn shouldComponentUpdate [nextprops nextstate]
|
(fn shouldComponentUpdate [nextprops nextstate]
|
||||||
@ -257,9 +270,9 @@
|
|||||||
|
|
||||||
(defn create-class [body]
|
(defn create-class [body]
|
||||||
{:pre [(map? body)]}
|
{:pre [(map? body)]}
|
||||||
(let [spec (cljsify body)
|
(->> body
|
||||||
res (.' util/react createClass spec)]
|
cljsify
|
||||||
(cache-react-class res res)))
|
(.' util/react createClass)))
|
||||||
|
|
||||||
(defn component-path [c]
|
(defn component-path [c]
|
||||||
(let [elem (some-> (or (some-> c (.' :_reactInternalInstance))
|
(let [elem (some-> (or (some-> c (.' :_reactInternalInstance))
|
||||||
@ -285,20 +298,21 @@
|
|||||||
""))
|
""))
|
||||||
""))
|
""))
|
||||||
|
|
||||||
|
|
||||||
(defn fn-to-class [f]
|
(defn fn-to-class [f]
|
||||||
(assert (ifn? f) (str "Expected a function, not " (pr-str f)))
|
(assert (ifn? f) (str "Expected a function, not " (pr-str f)))
|
||||||
(warn-unless (not (and (fn? f)
|
(warn-unless (not (and (react-class? f)
|
||||||
(some? (some-> f .-prototype (.' :render)))))
|
(not (reagent-class? f))))
|
||||||
"Using native React classes directly in Hiccup forms "
|
"Using native React classes directly in Hiccup forms "
|
||||||
"is not supported. Use create-element or "
|
"is not supported. Use create-element or "
|
||||||
"adapt-react-class instead: " (let [n (util/fun-name f)]
|
"adapt-react-class instead: " (let [n (util/fun-name f)]
|
||||||
(if (empty? n) f n))
|
(if (empty? n) f n))
|
||||||
(comp-name))
|
(comp-name))
|
||||||
|
(if (reagent-class? f)
|
||||||
|
(cache-react-class f f)
|
||||||
(let [spec (meta f)
|
(let [spec (meta f)
|
||||||
withrender (assoc spec :reagent-render f)
|
withrender (assoc spec :reagent-render f)
|
||||||
res (create-class withrender)]
|
res (create-class withrender)]
|
||||||
(cache-react-class f res)))
|
(cache-react-class f res))))
|
||||||
|
|
||||||
(defn as-class [tag]
|
(defn as-class [tag]
|
||||||
(if-some [cached-class (cached-react-class tag)]
|
(if-some [cached-class (cached-react-class tag)]
|
||||||
@ -306,4 +320,6 @@
|
|||||||
(fn-to-class tag)))
|
(fn-to-class tag)))
|
||||||
|
|
||||||
(defn reactify-component [comp]
|
(defn reactify-component [comp]
|
||||||
(as-class comp))
|
(if (react-class? comp)
|
||||||
|
comp
|
||||||
|
(as-class comp)))
|
||||||
|
@ -728,6 +728,8 @@
|
|||||||
comp (atom c1)
|
comp (atom c1)
|
||||||
c2 (fn []
|
c2 (fn []
|
||||||
(apply vector @comp @arg))
|
(apply vector @comp @arg))
|
||||||
|
cnative (fn []
|
||||||
|
(into [:> @comp] @arg))
|
||||||
check (fn []
|
check (fn []
|
||||||
(is (= (:initial-state @res)
|
(is (= (:initial-state @res)
|
||||||
{:at 1 :args [@t]}))
|
{:at 1 :args [@t]}))
|
||||||
@ -741,7 +743,7 @@
|
|||||||
(reset! arg ["a" "c"])
|
(reset! arg ["a" "c"])
|
||||||
(r/flush)
|
(r/flush)
|
||||||
(is (= (:will-receive @res)
|
(is (= (:will-receive @res)
|
||||||
{:at 5 :args [@t [@comp "a" "b"]]}))
|
{:at 5 :args [@t [@comp "a" "c"]]}))
|
||||||
(is (= (:should-update @res)
|
(is (= (:should-update @res)
|
||||||
{:at 6 :args [@t [@comp "a" "b"] [@comp "a" "c"]]}))
|
{:at 6 :args [@t [@comp "a" "b"] [@comp "a" "c"]]}))
|
||||||
(is (= (:will-update @res)
|
(is (= (:will-update @res)
|
||||||
@ -762,6 +764,111 @@
|
|||||||
(is (= (:will-unmount @res)
|
(is (= (:will-unmount @res)
|
||||||
{:at 10 :args [@t]})))))
|
{:at 10 :args [@t]})))))
|
||||||
|
|
||||||
|
|
||||||
|
(deftest lifecycle-native
|
||||||
|
(let [n1 (atom 0)
|
||||||
|
t (atom 0)
|
||||||
|
res (atom {})
|
||||||
|
oldprops (atom nil)
|
||||||
|
newprops (atom nil)
|
||||||
|
add-args (fn [key args]
|
||||||
|
(swap! res assoc key
|
||||||
|
{:at (swap! n1 inc)
|
||||||
|
:args (vec args)}))
|
||||||
|
render (fn [& args]
|
||||||
|
(this-as
|
||||||
|
c
|
||||||
|
(when @newprops
|
||||||
|
(is (= @newprops) (first args))
|
||||||
|
(is (= @newprops) (r/props c)))
|
||||||
|
(is (= c (r/current-component)))
|
||||||
|
(is (= (first args) (r/props c)))
|
||||||
|
(add-args :render
|
||||||
|
{:children (r/children c)})
|
||||||
|
[:div (first args)]))
|
||||||
|
ls {:get-initial-state
|
||||||
|
(fn [& args]
|
||||||
|
(reset! t (first args))
|
||||||
|
(reset! oldprops (-> args first r/props))
|
||||||
|
(add-args :initial-state args)
|
||||||
|
{:foo "bar"})
|
||||||
|
:component-will-mount
|
||||||
|
(fn [& args]
|
||||||
|
(this-as c (is (= c (first args))))
|
||||||
|
(add-args :will-mount args))
|
||||||
|
:component-did-mount
|
||||||
|
(fn [& args]
|
||||||
|
(this-as c (is (= c (first args))))
|
||||||
|
(add-args :did-mount args))
|
||||||
|
:should-component-update
|
||||||
|
(fn [& args]
|
||||||
|
(this-as c (is (= c (first args))))
|
||||||
|
(add-args :should-update args) true)
|
||||||
|
:component-will-receive-props
|
||||||
|
(fn [& args]
|
||||||
|
(reset! newprops (-> args second second))
|
||||||
|
(this-as c
|
||||||
|
(is (= c (first args)))
|
||||||
|
(add-args :will-receive (into [(dissoc (r/props c) :children)]
|
||||||
|
(:children (r/props c))))))
|
||||||
|
:component-will-update
|
||||||
|
(fn [& args]
|
||||||
|
(this-as c (is (= c (first args))))
|
||||||
|
(add-args :will-update args))
|
||||||
|
:component-did-update
|
||||||
|
(fn [& args]
|
||||||
|
(this-as c (is (= c (first args))))
|
||||||
|
(add-args :did-update args))
|
||||||
|
:component-will-unmount
|
||||||
|
(fn [& args]
|
||||||
|
(this-as c (is (= c (first args))))
|
||||||
|
(add-args :will-unmount args))}
|
||||||
|
c1 (r/create-class
|
||||||
|
(assoc ls :reagent-render render))
|
||||||
|
defarg [{:foo "bar"} "a" "b"]
|
||||||
|
arg (r/atom defarg)
|
||||||
|
comp (atom c1)
|
||||||
|
cnative (fn []
|
||||||
|
(into [:> @comp] @arg))
|
||||||
|
check (fn []
|
||||||
|
(is (= (:initial-state @res)
|
||||||
|
{:at 1 :args [@t]}))
|
||||||
|
(is (= (:will-mount @res)
|
||||||
|
{:at 2 :args [@t]}))
|
||||||
|
(is (= (:render @res)
|
||||||
|
{:at 3 :args [[:children ["a" "b"]]]}))
|
||||||
|
(is (= (:did-mount @res)
|
||||||
|
{:at 4 :args [@t]}))
|
||||||
|
|
||||||
|
(reset! arg [{:f "oo"} "a" "c"])
|
||||||
|
(r/flush)
|
||||||
|
|
||||||
|
(is (= (:will-receive @res)
|
||||||
|
{:at 5 :args [{:foo "bar"} "a" "b"]}))
|
||||||
|
(let [a (:should-update @res)
|
||||||
|
{at :at
|
||||||
|
[this oldv newv] :args} a]
|
||||||
|
(is (= at 6))
|
||||||
|
(is (= (count (:args a)) 3))
|
||||||
|
(is (= (js->clj oldv) (js->clj [@t @oldprops])))
|
||||||
|
(is (= newv [@t @newprops])))
|
||||||
|
(let [a (:will-update @res)
|
||||||
|
{at :at
|
||||||
|
[this newv] :args} a]
|
||||||
|
(is (= at 7))
|
||||||
|
(is (= newv [@t @newprops])))
|
||||||
|
(is (= (:render @res)
|
||||||
|
{:at 8 :args [[:children ["a" "c"]]]}))
|
||||||
|
(let [a (:did-update @res)
|
||||||
|
{at :at
|
||||||
|
[this oldv] :args} a]
|
||||||
|
(is (= at 9))
|
||||||
|
(is (= oldv [@t @oldprops]))))]
|
||||||
|
(when isClient
|
||||||
|
(with-mounted-component [cnative] check)
|
||||||
|
(is (= (:will-unmount @res)
|
||||||
|
{:at 10 :args [@t]})))))
|
||||||
|
|
||||||
(defn foo []
|
(defn foo []
|
||||||
[:div])
|
[:div])
|
||||||
|
|
||||||
@ -817,7 +924,7 @@
|
|||||||
(is (= e
|
(is (= e
|
||||||
{:error (lstr "Error rendering component (" stack1 ")")})))
|
{:error (lstr "Error rendering component (" stack1 ")")})))
|
||||||
|
|
||||||
(let [e (debug/track-warnings #(r/reactify-component nat))]
|
(let [e (debug/track-warnings #(r/as-element [nat]))]
|
||||||
(is (re-find #"Using native React classes directly"
|
(is (re-find #"Using native React classes directly"
|
||||||
(-> e :warn first))))
|
(-> e :warn first))))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user