mirror of https://github.com/status-im/reagent.git
Handle form-2 and form-3 components
This commit is contained in:
parent
9042db423f
commit
678e8adf7b
|
@ -402,59 +402,68 @@
|
||||||
|
|
||||||
(defn functional-render [jsprops]
|
(defn functional-render [jsprops]
|
||||||
(let [argv (.-argv jsprops)
|
(let [argv (.-argv jsprops)
|
||||||
tag (.-tag jsprops)
|
tag (.-tag jsprops)]
|
||||||
res (if util/*non-reactive*
|
(if util/*non-reactive*
|
||||||
(apply tag argv)
|
(let [res (apply tag argv)]
|
||||||
;; Create persistent ID for each rendered functional component,
|
(cond
|
||||||
;; this is used to store internal Reagent state, like render
|
(vector? res) (as-element res)
|
||||||
;; reaction etc. in a separate store where changes doesn't
|
(ifn? res) (let [f (if (reagent-class? res)
|
||||||
;; trigger render.
|
(fn [& args]
|
||||||
(let [[id _] (react/useState (js/Symbol))
|
(as-element (apply vector res args)))
|
||||||
[_ update-count] (react/useState 0)
|
res)]
|
||||||
reagent-state (or (gobj/get fun-component-state id)
|
(as-element (apply f argv)))
|
||||||
;; TODO: Mock state atom?
|
:else res))
|
||||||
(let [obj #js {:forceUpdate (fn [] (update-count inc))
|
(let [;; Create persistent ID for each rendered functional component,
|
||||||
:cljsMountOrder (batch/next-mount-count)}]
|
;; this is used to store internal Reagent state, like render
|
||||||
(gobj/set fun-component-state id obj)
|
;; reaction etc. in a separate store where changes doesn't
|
||||||
obj))]
|
;; trigger render.
|
||||||
|
[id _] (react/useState (js/Symbol))
|
||||||
|
|
||||||
(react/useEffect
|
;; Use counter to trigger render manually.
|
||||||
(fn mount []
|
[_ update-count] (react/useState 0)
|
||||||
(fn unmount []
|
|
||||||
(some-> (.-cljsRatom reagent-state) ratom/dispose!)
|
|
||||||
(gobj/remove fun-component-state id)))
|
|
||||||
;; Only run effect once on mount and unmount
|
|
||||||
#js [])
|
|
||||||
|
|
||||||
;; Note: it might be possible to mock some React Component
|
;; This object mimics React Class attributes and methods.
|
||||||
;; methods in the object and use it as *current-component*
|
;; To support form-2 components, even the render fn needs to
|
||||||
|
;; be stored as it is created during the first render,
|
||||||
|
;; and subsequent renders need to retrieve the created fn.
|
||||||
|
reagent-state (or (gobj/get fun-component-state id)
|
||||||
|
(let [obj #js {:forceUpdate (fn [] (update-count inc))
|
||||||
|
:cljsMountOrder (batch/next-mount-count)
|
||||||
|
:renderFn tag}]
|
||||||
|
(gobj/set fun-component-state id obj)
|
||||||
|
obj))]
|
||||||
|
|
||||||
;; TODO: If return value is ifn?, consider form-2 component.
|
(react/useEffect
|
||||||
|
(fn mount []
|
||||||
|
(fn unmount []
|
||||||
|
(some-> (.-cljsRatom reagent-state) ratom/dispose!)
|
||||||
|
(gobj/remove fun-component-state id)))
|
||||||
|
;; Only run effect once on mount and unmount
|
||||||
|
#js [])
|
||||||
|
|
||||||
(assert-callable tag)
|
(assert-callable tag)
|
||||||
|
|
||||||
(batch/mark-rendered reagent-state)
|
(batch/mark-rendered reagent-state)
|
||||||
|
|
||||||
;; static-fns :render
|
;; static-fns :render
|
||||||
(if-let [rat (.-cljsRatom reagent-state)]
|
(let [res (if-let [rat (.-cljsRatom reagent-state)]
|
||||||
(._run rat false)
|
(._run rat false)
|
||||||
(ratom/run-in-reaction
|
(ratom/run-in-reaction
|
||||||
;; Mock Class component API
|
;; Mock Class component API
|
||||||
#(binding [*current-component* reagent-state]
|
#(binding [*current-component* reagent-state]
|
||||||
(apply tag argv))
|
(apply (.-renderFn reagent-state) argv))
|
||||||
reagent-state
|
reagent-state
|
||||||
"cljsRatom"
|
"cljsRatom"
|
||||||
batch/queue-render
|
batch/queue-render
|
||||||
rat-opts))))]
|
rat-opts))]
|
||||||
;; do-render
|
(cond
|
||||||
;; wrap-render
|
(vector? res) (as-element res)
|
||||||
(cond
|
(ifn? res) (let [;; If original fn returned class (create-class) wrap in fn and call that.
|
||||||
(vector? res) (as-element res)
|
f (if (reagent-class? res)
|
||||||
;; FIXME: Support form-2 components???
|
(fn [& args]
|
||||||
; (ifn? res) (let [f (if (reagent-class? res)
|
(as-element (apply vector res args)))
|
||||||
; (create-class
|
res)]
|
||||||
; {:reagent-render (fn [& args]
|
;; Store the returned fn in state, so it will be used in following render calls.
|
||||||
; (as-element (apply vector res args)))})
|
(set! (.-renderFn reagent-state) f)
|
||||||
; res)]
|
(as-element (apply f argv)))
|
||||||
; f)
|
:else res))))))
|
||||||
:else res)))
|
|
||||||
|
|
Loading…
Reference in New Issue