reagami
v0.0.36
Published

Maintainers
Readme
Reagami
Fold your state into the DOM!
A minimal zero-deps Reagent-like in Squint and CLJS.
Usage
Quickstart example:
(ns my-app
(:require ["https://esm.sh/reagami" :as reagami]))
(def state (atom {:counter 0}))
(defn my-component []
[:div
[:div "Counted: " (:counter @state)]
[:button {:on-click #(swap! state update :counter inc)}
"Click me!"]])
(defn render []
(reagami/render (js/document.querySelector "#app") [my-component]))
(add-watch state ::render (fn [_ _ _ _]
(render)))
(render)(Open this example on the Squint playground)
In ClojureScript you would add this library to your deps.edn :deps as follows:
io.github.borkdude/reagami {:git/sha "<latest-sha>" :git/tag "<latest-tag>"}and then require it with (:require [reagami.core :as reagami]).
Reagami supports:
- Building small reactive apps with the only dependency being Squint or CLJS. Smallest app with Squint after minification is around 5kb gzip.
- Rendering hiccup into a container DOM node. The only public function is
render. - Event handlers via
:on-click,:on-input, etc. - Default attributes:
:default-value, etc. for uncontrolled components - Id and class short notation:
[:div#foo.class1.class2] - Disabling properties with
false:[:button {:disabled (not true)}] :stylemaps:{:style {:background-color :green}}:on-renderhook. See docs here.
Reagami does NOT support:
- Auto-rerendering by auto-watching custom atoms. Instead you use
add-watch+renderon regular atoms or you callrenderyourself. - Local state and form-2 components, although you can mimic local state by using nested renders like in this example.
- React hooks (it doesn't use React)
Reagami uses a basic patching algorithm explained in this blog post. It may become more advanced in the future, but the (fun) point of this library at this point is that it's small, underengineered and thus suited for educational purposes.
For a more fully featured version of Reagent in squint, check out Eucalypt.
:on-render
The :on-render hook can be used to do something after a DOM node is mounted, updated or unmounted.
It takes 3 arguments: (fn [node lifecycle data])
node: the DOM node that is mounted, updated or unmounted.lifecycle: one of:mount,:updateor:unmountdata: the result of the:on-renderfunction every time it is called. By returning data you can pass data from one lifecycle to another. E.g. when you mount a JS component, you can return{:unmount unmount}so you can call the unmount function in the:unmountlifecycle.
Example:
(fn [node lifecycle {:keys [unmount updates] :as data}]
(case lifecycle
:mount
{:unmount (install-clock! node)
:updates 0}
:update
(update data :updates inc)
:unmount
(do
(println "Number of updates in total: " updates)
(unmount))))See a full working example on the playground.
Examples
Examples on the Squint playground:
License
MIT
