mirror of https://github.com/status-im/reagent.git
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)))
|
||||
|
||||
(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]
|
||||
(-> (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]
|
||||
(-> (get-argv c) nil? not))
|
||||
(defn ^boolean reagent-class? [c]
|
||||
(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]
|
||||
(.' c :cljsReactClass))
|
||||
|
@ -69,9 +85,6 @@
|
|||
|
||||
;;; Rendering
|
||||
|
||||
(defn ^boolean reagent-class? [c]
|
||||
(and (fn? c)
|
||||
(some? (some-> c .-prototype (.' :reagentRender)))))
|
||||
|
||||
(defn wrap-render [c]
|
||||
(let [f (.' c :reagentRender)
|
||||
|
@ -146,8 +159,8 @@
|
|||
(this-as c (reset! (state-atom c) (.call f c c))))
|
||||
|
||||
:componentWillReceiveProps
|
||||
(fn componentWillReceiveProps [props]
|
||||
(this-as c (.call f c c (get-argv c))))
|
||||
(fn componentWillReceiveProps [nextprops]
|
||||
(this-as c (.call f c c (props-argv c nextprops))))
|
||||
|
||||
:shouldComponentUpdate
|
||||
(fn shouldComponentUpdate [nextprops nextstate]
|
||||
|
@ -257,9 +270,9 @@
|
|||
|
||||
(defn create-class [body]
|
||||
{:pre [(map? body)]}
|
||||
(let [spec (cljsify body)
|
||||
res (.' util/react createClass spec)]
|
||||
(cache-react-class res res)))
|
||||
(->> body
|
||||
cljsify
|
||||
(.' util/react createClass)))
|
||||
|
||||
(defn component-path [c]
|
||||
(let [elem (some-> (or (some-> c (.' :_reactInternalInstance))
|
||||
|
@ -285,20 +298,21 @@
|
|||
""))
|
||||
""))
|
||||
|
||||
|
||||
(defn fn-to-class [f]
|
||||
(assert (ifn? f) (str "Expected a function, not " (pr-str f)))
|
||||
(warn-unless (not (and (fn? f)
|
||||
(some? (some-> f .-prototype (.' :render)))))
|
||||
(warn-unless (not (and (react-class? f)
|
||||
(not (reagent-class? f))))
|
||||
"Using native React classes directly in Hiccup forms "
|
||||
"is not supported. Use create-element or "
|
||||
"adapt-react-class instead: " (let [n (util/fun-name f)]
|
||||
(if (empty? n) f n))
|
||||
(comp-name))
|
||||
(if (reagent-class? f)
|
||||
(cache-react-class f f)
|
||||
(let [spec (meta f)
|
||||
withrender (assoc spec :reagent-render f)
|
||||
res (create-class withrender)]
|
||||
(cache-react-class f res)))
|
||||
(cache-react-class f res))))
|
||||
|
||||
(defn as-class [tag]
|
||||
(if-some [cached-class (cached-react-class tag)]
|
||||
|
@ -306,4 +320,6 @@
|
|||
(fn-to-class tag)))
|
||||
|
||||
(defn reactify-component [comp]
|
||||
(as-class comp))
|
||||
(if (react-class? comp)
|
||||
comp
|
||||
(as-class comp)))
|
||||
|
|
|
@ -728,6 +728,8 @@
|
|||
comp (atom c1)
|
||||
c2 (fn []
|
||||
(apply vector @comp @arg))
|
||||
cnative (fn []
|
||||
(into [:> @comp] @arg))
|
||||
check (fn []
|
||||
(is (= (:initial-state @res)
|
||||
{:at 1 :args [@t]}))
|
||||
|
@ -741,7 +743,7 @@
|
|||
(reset! arg ["a" "c"])
|
||||
(r/flush)
|
||||
(is (= (:will-receive @res)
|
||||
{:at 5 :args [@t [@comp "a" "b"]]}))
|
||||
{:at 5 :args [@t [@comp "a" "c"]]}))
|
||||
(is (= (:should-update @res)
|
||||
{:at 6 :args [@t [@comp "a" "b"] [@comp "a" "c"]]}))
|
||||
(is (= (:will-update @res)
|
||||
|
@ -762,6 +764,111 @@
|
|||
(is (= (:will-unmount @res)
|
||||
{: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 []
|
||||
[:div])
|
||||
|
||||
|
@ -817,7 +924,7 @@
|
|||
(is (= e
|
||||
{: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"
|
||||
(-> e :warn first))))
|
||||
|
||||
|
|
Loading…
Reference in New Issue