Reagent, a wrapper for React.js
Posted On February 18, 2017 by Geeta Priya filed under Enterprise
As the complexity of web applications has increased, better tools to tackle the same has also emerged.
- JQuery, library was used for easier user-interaction to manipulate DOM but still only the server had to re-render the DOM.
- MVC frameworks took over the job of manipulation of DOM. They also enabled re-rendering of the DOM in the client. But as the entire DOM was re-rendered, it was relatively slow.
- New component oriented architecture was adopted and UI was composed from components. As only the changed DOM was re-rendered, re-rendering was faster.
- ClojureScript wrappers for React.js re-rendered even faster. In React.js the components are objects. In these wrappers components are just functions. The persistent data structures used by the language also contributed to this improved performance.
There is a lot of activity in ClojureScript community around React.js .Om, Reagent,Quiescent and Rum are some of the wrappers in ClojureScript for React.js. Unlike “Om” , another wrapper which is thinner wrapper over React and exposes React’s API and lifecycle events, Regent allows you to define React UIs of arbitrary complexity using only plain ClojureScript functions & data and describe it using Hiccup-like syntax which is very concise and easy to read. Our application can be built together only using bunch of very basic concepts. Generating or modifying Reagent components is just a matter of manipulating this data structure. React itself is very fast. Reagent is able to be even faster because of the functional paradigm of ClojureScript and the optimizations done in it. Above all a separate state management tool like Redux is not necessary, as “atoms” – a feature of ClojureScript – can handle state management.
We can use reagent template to generate the sample as under:
lein new reagent myproject
You can start the server by executing
When figwheel server starts, you will be asked to navigate to http://0.0.0.0:3449.If you do so you will see the browser as in Figure-1.Have a look at core.clj and see the the home-page component definition
(defn home-page 
The general format for creating an HTML element inside a component is to create a vector whose first element is a keyword giving the HTML element name, a map of its attributes (if any), and the element content, which may contain other elements.
Under the above component, the function mount-root() is defined calling the render() provided by reagent. Reagent’s render function takes two arguments: 1)a call to the component and 2) the DOM node where you want the component rooted, in this case, the app element. Modify the function as under:
(defn hello [name]
Modify the mount-to as under:
|(defn mount-root 
(reagent/render [hello] (.getElementById js/document "app")))
Now we will refresh the browser and can see Figure-2.You can include other components within a component as shown below:
|(defn comment-list  ;;comment-list component
"Hello, world! I am a CommentList"])
(defn comment-form  ;;comment-form component
(defn comment-box  ;; comment-box composed from other two components
If Modify mount-to accordingly and refresh the browser, you can see Figure-3.
React is very efficient in managing state. You simply update component internal state and then its UI is re-rendered accordingly. You do not have to deal with programming state transitions by hand which results in reduction of code complexity. The lifecycle method getInitialState() and componentDidMount() methods like setState(), setInterval() are used. In ClojureScript, almost everything is immutable. To accomplish mutability ClojureScript uses concept of atoms. Atoms are references to objects which needs to be dereferenced in order to obtain object instance. Think about them as similar thing as pointers in C. Common and viable practice is to define all of your application state in one atom. Reagent own version of atom. It works exactly like the one in clojure.core, except that it keeps track of every time it is deref’ed. Any component that uses an atom is automagically re-rendered when its value changes; the de-referenced atom is modified with swap! According to reagent doc, you can return a new function while defining components, so as to avoid usage of getInitialState and componentDidMount. This allows for more complex binding scenarios than in typical use of React. The distinction in React between props and state is not there in Reagent.
(def click-count (atom 0))
(defn mount-root 
If you refresh the browser, you can see Figure-4.
(defn timer-component 
.Reagent benefits from fast pointer comparisons between changed ClojureScript data structures and triggering of re-rendering of components only when it is really needed.
You can modify mount-root and refresh the browser and see the result/ the counter incrementing as in Figure-5. In short , number of elapsed seconds is kept in its own atom - in this case unique state of component. Most common way to mutate atom value is to use built-in ClojureScript function swap!.Call to swap! accepts function as argument that is applied to value of atom and stored.