Reagent provides a minimalistic interface between ClojureScript and React. It allows you to define efficient React components using nothing but plain ClojureScript functions and data, that describe your UI using a Hiccup-like syntax.

In this article, we are going to show you how you can write a blog post with interactive reagent component inside a blog post using the klipse plugin.

In this context, interactive means that the reader of the blog post can edit the code of the component.

It’s super simple:

  1. You add the klipse javascript tag to your blog posts as explained here.
  2. You require reagent.core in a clojure snippet.
  3. You define and render your component in a clojure snippet.

minority

Hello World!

Let’s start with a Hello World! reagent component:

First, we require reagent.core - in a clojure snippet:

(Please be a bit patient, it takes some time to load both react.js and reagent code into this web page…)

(require '[reagent.core :as r])

Then, we define and render our component - in a reagent snippet:

(defn hello [name]
[:p (str "Hello " name "!")])

[hello "Klipse"]

So easy. Right?

Go ahead, enjoy the interactivity: modify the code of the component and see how it is rendered as you type.

Now, let’s see how it works…

Under the hood

The code snippet with [hello "World"] is not a regular clojure snippet: it’s a reagent snippet. Klipse wraps the last expression of the snippet in a call to reagent.dom/render and passes to it the dom element that is right after the code snippet (a.k.a the klipsecontainer).

Nothing magic, we can do it manually using a regular clojure snippet like this:

(reagent.dom/render [hello "World!"] js/klipse-container)

Each klipse snippets has a dom sibling associated to it and it is accessible by js/klipse-container.

And if your component doesn’t require any argument, you even don’t need to wrap into into a vector - klipse will wrap it into a vector for you - this nice idea was emitted and implemented by Timothy Pratley:

(defn tim []
  [:span "Timothy"])

(defn hello-there []
    [:p "Thanks " [tim]])

Now, for the fun, let’s take a look at a more interesting reagent component…

A more interesting example: A BMI calculator

Here is a nice example from Reagent Website that shows how to implement a BMI calculator with reagent:

(def bmi-data (r/atom {:height 180 :weight 80}))

(defn calc-bmi []
  (let [{:keys [height weight bmi] :as data} @bmi-data
        h (/ height 100)]
    (if (nil? bmi)
      (assoc data :bmi (/ weight (* h h)))
      (assoc data :weight (* bmi h h)))))

(defn slider [param value min max]
  [:input {:type "range" :value value :min min :max max
           :style {:width "100%"}
           :on-change (fn [e]
                        (swap! bmi-data assoc param (.-target.value e))
                        (when (not= param :bmi)
                          (swap! bmi-data assoc :bmi nil)))}])

(defn bmi-component []
  (let [{:keys [weight height bmi]} (calc-bmi)
        [color diagnose] (cond
                          (< bmi 18.5) ["orange" "underweight"]
                          (< bmi 25) ["inherit" "normal"]
                          (< bmi 30) ["orange" "overweight"]
                          :else ["red" "obese"])]
    [:div
     [:h3 "BMI calculator"]
     [:div
      "Height: " (int height) "cm"
      [slider :height height 100 220]]
     [:div
      "Weight: " (int weight) "kg"
      [slider :weight weight 30 150]]
     [:div
      "BMI: " (int bmi) " "
      [:span {:style {:color color}} diagnose]
      [slider :bmi bmi 10 50]]]))

What else now?

Now, I’m expecting all the cool guys of the clojurecript community to write incredible blog posts with interactive reagent code snippets…

If you haven’t done it already, please give a github star to reagent and klipse.

A final note

It is also possible to evaluate reagent code snippets in the browser with the great CljsFiddle by @escherize.

A last final note

If you really want to become a reagent master, take a video course on reagent.