New introduction to Respo, a virtual DOM library in ClojureScript

Just finished updating Respo’s home page http://respo.site/ several days before. I’m trying to introduce Respo to more developers in Clojure community. It has only small part of features from React, but It’s more pure since it’s written totally in ClojureScript. Try if it appeals to you. :slight_smile:


Create elements in Clojure syntax:

(div {:class-name "demo"
      :style {:color :red
              :font-size 16
              :font-family "Josefin Sans"}
      :on-click (fn [event dispatch! mutate!])})

; respo.macros/div

Nest child elements:

(div {}
  (span {})
  (div {}))

; respo.macros/span

Add text nodes:

(div {}
  (<> "text")
  (<> "text with style" {:color :red}))

; respo.macros/<>

Create Components

To define components, use defcomp, it’s a Macro:

(defcomp comp-demo [p1 p2]
  (div {}
    (<> p1)
    (<> p2)))

(comp-demo :a :b)

; respo.macros/defcomp

Use render! to mount a component. It also handles re-rendered if mounting already happened.

(defonce *store (atom {}))
(defn dispatch! [op op-data] (swap! *store assoc :a 1))

(render! mount-target (comp-container @*store) dispatch!)

; respo.core/render!

To hot replace app, use render! function. clear-cache! is for clearing internal rendering caches:

(defn reload! []
  (clear-cache!)
  (render! mount-target (comp-container @*store) dispatch!))

; respo.core/clear-cache!

States Management

Respo uses an Atom to maintain global states. Global states and “Single Source of Truth” are prefered:

(defonce *store (atom {}))
(defn dispatch! [op op-data] (swap! *store assoc :a 1))

(add-watch *store :changes
           (fn []
               (render! mount-target (comp-container @*store) dispatch!)))

Respo has supports for component-level states. But is designed in an awkward syntax in order to make sure it’s consistent with “Single Source of Truth”. Read about mutate! and cursor-> in the docs.

Ecosystem

During developing Respo, a bunch of libraries are added:

  • hsl – a function that returns color in string
  • ui – basic UI styles collected based on Flexbox
  • markdown – subset Markdown syntax rendering to virtual DOM
  • router – HTML5 router library decoupled from view part
  • tiny-app – a macro for inialising app in a easy way
  • reel – time travelling developing tool
  • value – to display collections
  • message – displaying message on top-right corner
  • global-popup and inflow-popup

Try Respo

Now it’s your turn to read Guide and try Respo:

An easy way to use Respo is using tiny-app. It’s a macro that handles dirty works in passing in configurations.

For Advanced developers, probably the best way to understand Respo is to read code of how the author is using it. Contact me on Twitter anytime if you got questions.

Send feedbacks on issues if you want to improve this page. Old versions.

3 Likes

Hey @jiyinyiyong! It was really interesting to read the code. Do you have any ideas what’s the performance like? Is it faster/slower than React/sablono/rum/reagent/whatever on any regular workflow?

I tried but turned out I haven’t bring enough optimizations Respo need to match React’s performance. In Respo it’s just a really DOM diff algorithm that i can implement in my knowledge. There are many chances it can be optimized, for example, batching.

Now it’s definitely slower compared to React. Only good optimization in Respo currently is immutable data, which help Respo skips a lot of redundant component re-rendering.