Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Reagent component util
(defn component
"Experimental! A Reagent 'component' is a (fn [& [props children this]]) that:
* May have special metadata for React lifecycle methods.
* Returns either Hiccup data, or a nested (usu. post-setup) component[1].
This util makes writing Reagent components a little more convenient:
:render (fn [node_ & cmpt-args]) -> Hiccup data, or nested component[1].
;; Additional methods optional:
:did-mount (fn [node])
:did-update (fn [node])
:will-unmount (fn [node]))
-> (fn [& cmpt-args]) component.
[1] Nb note that nested component fns are _only_ called when one or more of
their input args have actually changed!!"
[& lifecycle-methods]
(let [methods (apply hash-map lifecycle-methods)
node_ (atom nil)]
(assert (ifn? (:render methods)) "No :render lifecycle method provided")
(assert (every? #{:render :did-mount :did-update :will-unmount} (keys methods))
"Bad lifecycle method key(s) provided")
(partial (:render methods) node_) ; [& cmpt-args] -> [node_ & cmpt-args]
(merge methods
;; [rootNode] -> [node] + maintain node_:
(fn [node*]
;; (debugf "component-did-mount: %s" node*)
(let [node (reagent/dom-node node*)]
(reset! node_ node)
(when-let [mf (or (:component-did-mount methods)
(:did-mount methods))]
(mf node))))}
;; [prevProps prevState rootNode] -> [node]:
(when-let [mf (or (:component-did-update methods)
(:did-update methods))]
(fn [_ _ node*]
;; (debugf "component-did-update: %s" node*)
(let [node (reagent/dom-node node*)]
(mf node)))})
;; [] -> [node]:
(when-let [mf (or (:component-will-unmount methods)
(:will-unmount methods))]
(fn []
(let [node @node_]
;; (debugf "component-will-unmount: %s" node)
(mf node)))})))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment