Adopting Reagent for Reactive UIs in ClojureScript
Reagent lets ClojureScript developers write React UI in Hiccup syntax, using atoms for reactive state and hot reloading via shadow‑cljs. This blog explains its benefits, shows a counter example, discusses performance trade‑offs, and gives a practical checklist to get started.
18 Nov 2025, 21:05 UTC

Why Reagent Might Be the Right Choice for Your Next UI Project
When building a single‑page application in ClojureScript, you quickly hit the same decision point that many front‑end teams face: how to bridge the language’s functional style with the React ecosystem that powers most modern UIs. Reagent offers a lightweight wrapper that lets you write React components in familiar Hiccup syntax while still reaping React’s performance benefits. This blog walks through the core advantages, a concrete counter example, and the trade‑offs you should consider before adding Reagent to your stack.
Core Benefits at a Glance
- Hiccup syntax – Write JSX‑like structures as ClojureScript maps and vectors.
- Automatic diffing – Under the hood Reagent translates Hiccup to React elements and keeps the DOM in sync.
- Atom‑driven state – ClojureScript atoms trigger re‑renders only for components that dereference them.
- Hot reloading – Works seamlessly with
shadow-cljs’s watch mode for instant feedback. - Interop – Native JavaScript libraries are accessible via
js/andgoog.require.
Hands‑On Example: A Simple Counter
Below is the minimal code you’d place in src/main.cljs to create a counter that increments on button click. No build configuration is shown, but the example assumes you’re running shadow-cljs with a dev build that serves index.html on http://localhost:3000.
(ns counter.core
(:require [reagent.core :as r]
[reagent.dom :as d]))
;; 1. Define a global atom to hold the count
(defonce counter (r/atom 0))
;; 2. Build a component that dereferences the atom
(defn counter-view []
[:div
[:h1 "Current count: " @counter]
[:button {:on-click #(swap! counter inc)}
"Increment"]])
;; 3. Mount the component into the DOM
(d/render [counter-view] (.getElementById js/document "app"))
Save the file, run shadow-cljs watch app, and open http://localhost:3000. You should see the counter start at 0 and increment each time you click the button, all without a page refresh.
Verifying the Result
- UI update – Click the button and confirm the number on screen changes instantly.
- Hot reload – Edit the
counter-viewcomponent (e.g., change the title text), save, and see the browser update without a full rebuild. - React DevTools – Open the inspector and locate the Reagent component; verify that its props and state reflect the atom’s value.
Trade‑Offs and Performance Considerations
Reagent’s tight coupling to React means you inherit React’s versioning cycle. Updating React from 17 to 18, for instance, may require you to bump Reagent or adjust the binding code. Keep an eye on the Reagent releases when you plan major upgrades.
Another subtle performance pitfall arises when a component dereferences a large atom or many atoms. Each dereference schedules a re‑render, which can lead to unnecessary DOM updates. Two common mitigations are:
reagent.core/with-let– Memoize expensive calculations inside the component.reagent.core/partial– Create a partially applied component that only re‑renders when its specific props change.
When to Choose Reagent
- You’re comfortable with ClojureScript’s immutable data structures and prefer a functional style for UI.
- You want rapid iteration: the combination of Reagent and
shadow-cljsprovides instant hot reloading. - Your project already uses React or you plan to integrate with existing React libraries.
Actionable Checklist
- Install
reagentandreagent.domvianpm install reagent reagent.domoryarn add reagent reagent.dom. - Add a
devbuild inshadow-cljs.ednthat points to your entry point. - Create the minimal counter example above, run
shadow-cljs watch app, and confirm hot reload works. - Profile with React DevTools to ensure only the components that need to update are re‑rendered.
- Plan for React upgrades: keep Reagent on a stable release and test your UI after each major React bump.
With these steps, you can confidently decide whether Reagent’s blend of ClojureScript elegance and React performance fits your project’s needs.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.