Skip to content

Instantly share code, notes, and snippets.

@Ionshard
Created November 1, 2017 16:15
Show Gist options
  • Select an option

  • Save Ionshard/fa75b52b9f4c31d382d42d98823ab9cc to your computer and use it in GitHub Desktop.

Select an option

Save Ionshard/fa75b52b9f4c31d382d42d98823ab9cc to your computer and use it in GitHub Desktop.
Clojure(script) code to allow creating components that behave like reagent wrapped react components.
(ns epiphany.component)
(defn extract-props [v]
(let [p (nth v 1 nil)]
(if (map? p) p)))
(defn extract-children [v]
(let [p (nth v 1 nil)
first-child (if (or (nil? p) (map? p)) 2 1)]
(if (> (count v) first-child)
(subvec v first-child))))
#?(:clj
(defmacro defcomponent
"This macro allows you to define a component that works much like the react
classes created by reagent, including the optional first props parameter.
e.g. (defcomponent thingy [props children]
(let [label (:label props)]
(into [:div.thingy label] children)))
(thingy {:label :some} [:span :stuff])
=> props: {:label :some}, children; [[:span :stuff]]
(thingy [:span :stuff])
=> props: nil, children: [[:span :stuff]]"
[sym args & body]
`(defn ~sym [& args#]
(let [props# (extract-props args#)
children# (extract-children args#)]
((fn ~args @~body) props# children#)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment