reagent

A minimalistic ClojureScript interface to React.js

Subscribe to updates I use reagent


Statistics on reagent

Number of watchers on Github 2936
Number of open issues 45
Average time to close an issue about 1 month
Main language Clojure
Average time to merge a PR 14 days
Open pull requests 30+
Closed pull requests 17+
Last commit 7 months ago
Repo Created almost 5 years ago
Repo Last Updated 6 months ago
Size 2.24 MB
Homepage http://reagent-pr...
Organization / Authorreagent-project
Contributors17
Page Updated
Do you use reagent? Leave a review!
View open issues (45)
View reagent activity
View on github
Latest Open Source Launches
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating reagent for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

Reagent

A simple ClojureScript interface to React.

Reagent provides a way to write efficient React components using (almost) nothing but plain ClojureScript functions.

Prerequisites

Usage

To create a new Reagent project simply run:

lein new reagent myproject

If you wish to only create the assets for ClojureScript without a Clojure backend then do the following instead:

lein new reagent-frontend myproject

This will setup a new Reagent project with some reasonable defaults, see here for more details.

To use Reagent in an existing project you add this to your dependencies in project.clj:

Clojars Project
CircleCI

This is all you need to do if you want the standard version of React. If you want the version of React with addons, you'd use something like this instead:

[reagent "0.7.0" :exclusions [cljsjs/react]]
[cljsjs/react-with-addons "15.4.2-2"]

If you want to use your own build of React (or React from a CDN), you have to use :exclusions variant of the dependency, and also provide a file named cljsjs/react.cljs, containing just (ns cljsjs.react), in your project.

Examples

Reagent uses Hiccup-like markup instead of React's sort-of html. It looks like this:

(defn some-component []
  [:div
   [:h3 "I am a component!"]
   [:p.someclass 
    "I have " [:strong "bold"]
    [:span {:style {:color "red"}} " and red"]
    " text."]])

Reagent extends standard Hiccup in one way: it is possible to squeeze elements together by using a > character.

[:div
  [:p
    [:b "Nested Element"]]]

can be written as:

[:div>p>b "Nested Element"]

Since version 0.8: The :class attribute also supports collections of classes, and nil values are removed:

[:div {:class ["a-class" (when active? "active") "b-class"]}]

You can use one component inside another:

(defn calling-component []
  [:div "Parent component"
   [some-component]])

And pass properties from one component to another:

(defn child [name]
  [:p "Hi, I am " name])

(defn childcaller []
  [child "Foo Bar"])

You mount the component into the DOM like this:

(defn mountit []
  (r/render [childcaller]
            (.-body js/document)))

assuming we have imported Reagent like this:

(ns example
  (:require [reagent.core :as r]))

State is handled using Reagent's version of atom, like this:

(defonce click-count (r/atom 0))

(defn state-ful-with-atom []
  [:div {:on-click #(swap! click-count inc)}
   "I have been clicked " @click-count " times."])

Any component that dereferences a reagent.core/atom will be automatically re-rendered.

If you want do some setting up when the component is first created, the component function can return a new function that will be called to do the actual rendering:

(defn timer-component []
  (let [seconds-elapsed (r/atom 0)]
    (fn []
      (js/setTimeout #(swap! seconds-elapsed inc) 1000)
      [:div
       "Seconds Elapsed: " @seconds-elapsed])))

This way you can avoid using React's lifecycle callbacks like getInitialState and componentWillMount most of the time.

But you can still use them if you want to, either using reagent.core/create-class or by attaching meta-data to a component function:

(defonce my-html (r/atom ""))

(defn plain-component []
  [:p "My html is " @my-html])

(def component-with-callback
  (with-meta plain-component
    {:component-did-mount
     (fn [this]
       (reset! my-html (.-innerHTML (reagent/dom-node this))))}))

See the examples directory for more examples.

Performance

React is pretty darn fast, and so is Reagent. It should even be faster than plain old javascript React a lot of the time, since ClojureScript allows us to skip a lot of unnecessary rendering (through judicious use of React's shouldComponentUpdate).

The ClojureScript overhead is kept down, thanks to lots of caching.

Code size is a little bigger than React.js, but still quite small. The todomvc example clocks in at roughly 79K gzipped, using advanced compilation.

About

The idea and some of the code for making components atom-like comes from pump. The reactive-atom idea (and some code) comes from reflex.

The license is MIT.

reagent open issues Ask a question     (View All Issues)
  • almost 2 years ReactDOMServer cannot be optimized away.
  • almost 2 years Handle thrown exceptions
  • almost 2 years Consider replacing React with Preact
  • almost 2 years Warning: You are manually calling a React.PropTypes validation function ... See https://fb.me/react-warning-dont-call-proptypes for details.
  • almost 2 years Caret repositioning for TextField from material-ui
  • almost 2 years `:input` BUG in `0.6.0`
  • about 2 years React unique key not working with nesting shorthand >
  • about 2 years Ratom missing 'with-meta'
  • about 2 years Missing symbols when fast typing in IE (Internet Explorer)
  • about 2 years Possible removal of `findDOMNode()` from React in a future version
  • about 2 years Documentation doesn't define fundamental concepts
  • over 2 years Server-side rendering and .cljc?
  • over 2 years Allowing vec of keywords for class declaration (feature req)
  • over 2 years cursor watch not triggering when base atom is swapped.
  • over 2 years after-render fn executed before render when used in component-did-mount
  • over 2 years Reminder to update the README when 0.6 is released
  • over 2 years Forward setNativeProps to children
  • over 2 years News: add when it was created
  • almost 3 years Failures In Documentation
  • almost 3 years Add some macros for easy use of library
  • almost 3 years got some problems building the docs in gh-pages branch
  • almost 3 years Augmenting :component-will-receive-props to support positional args?
  • almost 3 years API documentation GitHub page
  • about 3 years Document reaction, make-reaction, and run!
  • about 3 years render-to-static-markup still warns about unique keys
  • about 3 years -peek-at cursors
  • over 3 years Developer documentation - how to run tests, etc.
  • over 3 years Support seqs of strings for :class
  • over 3 years React Native Support
  • over 3 years Reaction update behaviour
reagent open pull requests (View All Pulls)
  • Fix comment typos
  • Fix doc formatting
  • Updated codox to the latest one
  • Support for registering custom components
  • Handle sequences in hiccup like hiccup does
  • Support component getChildContext and childContextTypes
  • Setup PhantomJS testing
  • Revert #128 and add tests for ISwap implementations
  • Added support for collections in :class property
  • rename run! macro to react!
  • Make use of deftype constructor instead of interop
  • Reaction equality
  • Fix 'unreachable code' warnings in latest clojurescript
  • update readme version of react-with-addons
  • Create LICENSE
  • Upgraded react to 15.3.0
  • Feature proposal: add reaction that allows the user to explicitly notify watchers
  • Update React to 15.3.1
  • Add test showing Reagent running disposed reactions
  • Add link to API documentation
  • Make reagent self-host compatible
  • Support synthetic text input components
  • Upgrade to React 15.5 and use React ES6 class component
  • WIP: Test with foreign libs in node
  • Fix aget/aset use with objects
  • Update default React to version 16
  • Remove global karma dependencies
  • Catch not= throwing exceptions and log a warning
  • Draft user manual.
  • A few added details on ratom updates.
reagent questions on Stackoverflow (View All Questions)
  • Clojurescript/Reagent Unit testing component output and behaviour
  • Clojurescript/Reagent Unit testing component - simulate onChange
  • reagent render multiple components
  • Clojurescript/Reagent handling errors
  • Clojurescript/reagent without automatic rendering
  • Reagent: How to get new props from component-will-receive-props?
  • Putting data in a table in Clojurescript reagent
  • reagent-forms bind-fields ignores ':field', missing dependencies or incorrect usage?
  • How to update a reagent atom with a vector of maps in Clojure
  • Why are multi-methods not working as functions for Reagent/Re-frame?
  • Reagent React Clojurescript Warning: Every element in a seq should have a unique :key
  • Re-frame, reagent component life cycle and figwheel
  • Quil sketch on a Reagent canvas
  • Why does reagent not re-render my reagent-form on a state change
  • Reagent build without minified React library
  • How to pass focus from one element to another in Reagent(Clojurescript)?
  • Are reagent-forms meant to be using with re-frame?
  • When I refresh my Reagent page, Firebase data isn't available so I get an exception
  • clojurescript + reagent issue
  • How To Detect "Enter" Keypress in Reagent?
  • Interactive list in Reagent
  • touch left / touch right events in reagent
  • How to attach Bootstrap tooltip to Clojurescript Reagent component
  • Reagent generate a React Component that passes React.isValidClass(component)?
  • Why Radium doesn't work with Reagent (Clojurescript)?
  • Can reagent components have more than one top level HTML entities?
  • Reagent-Forms radio buttons displaying as text fields
  • on-click handler for a list item reagent clojurescript
  • How to use a ReactJS Component with Clojurescipt/Reagent
  • Making a simple countdown timer with Clojure/Reagent
reagent list of languages used
Other projects in Clojure