What is Reagent? The Minimalist Clojurescript React Wrapper
Reagent is a minimalist Clojure wrapper for React. It exposes all React APIs including hooks and is one of the most popular Clojure projects. This chapter is a theoretical introduction to Reagent. We'll learn about components, third-party integrations and local state.
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Tinycanva: Clojure for React Developers course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Tinycanva: Clojure for React Developers, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

[00:00 - 00:09] Reagent is a minimalist closure wrapper for React. It exposes all React APIs including hooks and is one of the most popular closure projects.
[00:10 - 00:18] This chapter is a theoretical introduction to Reagent. The code in this chapter doesn't apply directly to the tiny Kanwa project.
[00:19 - 00:29] Reagent uses hick up to define React components. Components are vectors where the first element is the element to render, second element is the props map and the third element is the child tree.
[00:30 - 00:39] Unlike React, we can use the keyword class instead of class name to define CSS classes. Also, these are just plain vectors.
[00:40 - 00:49] So everything that we have learned about data manipulation will work here. Like in this example, we used when to conditionally render a component.
[00:50 - 00:56] Functional components are vanilla closure functions. Reagent converts these functions into React components and renders them.
[00:57 - 01:13] To test the heading function out, we can move its definition to app core namespace and then swap it in place of hello as an argument to our render function. As soon as you save the file, shadow watch will hot reload the code in the browser.
[01:14 - 01:25] We can also use reagent.core/createElement method to create a functional component instead of hick up. This might be helpful in advanced use cases like animations.
[01:26 - 01:32] Native DOM elements are rendered using keywords like div or span. Custom components can be rendered using symbols.
[01:33 - 01:44] If we want to use the heading component that we defined earlier, we can use heading symbol as the first element of the vector. There are two kinds of reaction people have after reading this code.
[01:45 - 01:52] You either go "yeah, that's simple hick up, it's easy." Or you wonder why square brackets are used for custom components.
[01:53 - 02:00] Since heading is a plain closure function, we should be able to invoke it using parentheses. But we use square brackets instead.
[02:01 - 02:14] You can use round brackets too, but it is advisable to stick to vectors until you understand what is happening under the hood. Reagent transforms hick up forms into React components using create React class .
[02:15 - 02:27] If parentheses are used instead of square brackets, the heading function will be called and its output will be placed in the card component. That is the heading component will lose its identity as a React component.
[02:28 - 02:39] It will also lose the properties of a React component like the ability to be mermoiced or the ability to have local state. If square brackets are used, heading function will not be called.
[02:40 - 02:50] Reagent will package it into a React component and place it inside the card preserving the properties of a React component. React's ecosystem is exceptional.
[02:51 - 03:00] There are tons of high quality open source libraries like AND design and material design. With Reagent and Shadow, we can use these components easily.
[03:01 - 03:11] Reagents adapt React class function converts any React component into a Reagent component. There also exists a convenience method for third party components.
[03:12 - 03:21] The symbol colon greater than sign can be used as the first element of the vector followed by the component to render. We can rewrite our example as though.
[03:22 - 03:31] The special literal colon less than greater than sign is a shorthand to create React fragments. The following two forms are identical.
[03:32 - 03:44] Start heading and hash main are shorthand versions of class heading and id main respectively. Reactive atoms also known as ratums are special atoms that tie into a component 's life cycle.
[03:45 - 03:55] Here we have defined a counter component that accepts a reactive atom. This component can be rendered using the form counter or atom zero.
[03:56 - 04:07] Each time count changes, the component will be re-rendered. When we generate an app using createCLJ's app, a component similar to this one is generated automatically.
[04:08 - 04:15] You can check its source code in app.hello namespace. A ratum behaves just like a usual atom in terms of the API.
[04:16 - 04:28] Reagents reactive atoms can be shared across components. In this example, we defined the state at the namespace level and had two components, form and valve watcher read and write the state.
[04:29 - 04:39] If you are not able to follow along the atom usage, we suggest re-reading the chapters on atoms. The get function used for value prop gets the value for a key in a map.
[04:40 - 04:47] If no value is found, the default value, the third argument is returned. In this case, an empty string is returned.
[04:48 - 04:59] Reagent components are class-based and there is no easy way to use hooks in a class-based component. But we can expose reagent components as functional components using as element method.
[05:00 - 05:07] This lets us consume hooks. In this example, we defined a view that depends on React's use state hook.
[05:08 - 05:20] Instead of returning a hiccup form, we wrapped the hiccup form with our as element method. The important point to note here is that the view is not a functional reagent component anymore.
[05:21 - 05:51] Instead, it is a proper React component now and needs the colon greater than or a dap React class to work correctly. You can create a part of your UI layer in closure script and expose it to your React app as an NVM module.
[05:52 - 05:58] You need to write your functions in a different way though. React functional components accept two arguments, props and children.
[05:59 - 06:07] React calls your functions for you and passes the correct props. Here we have rewritten the heading component so it could be reactified.
[06:08 - 06:21] Notice how it is accepting a props argument instead of text and then rest ructure props to pull out the text. The CLJS2JS conversion is needed because React heading exists in the JS domain.
[06:22 - 06:27] Closure maps don't work in the JS domain. Things integers, boolines and other templated types too.
[06:28 - 06:38] Compound data types like maps, vectors, lists etc. need implicit conversion. The CLJS2JS function can also be replaced with the hash.js literal form.
[06:39 - 06:50] Since React heading component exists in the JS domain, reactive atoms will not work. In this chapter, we walked through reagent basics and learned about various way of creating components.
[06:51 - 07:03] We saw how to consume third party components, we also learned about reagents reactive atoms. Although we covered the functionality we need the most, a lot of reagent features remain untouched.
[07:04 - 07:30] We will uncover the API more as we build our application. [ Silence ]