Home

Awesome

Brutha

A simple and functional ClojureScript interface to React.

Rationale

Unlike Om and Reagent, Brutha is unopinionated on how you handle your application state. It doesn't include cursors or specialized atoms, instead relying on you to call a mount function with new state data. This is useful when you want to manage your application state yourself.

Installation

Add the following to your project :dependencies:

[brutha "0.2.1"]

Usage

Brutha doesn't include a dom namespace like Om, so you'll need to use a library like Flupot, Sablono or Kioo. In the examples we'll use Flupot.

First we'll require Brutha and Flupot:

(ns brutha.example
  (:require [brutha.core :as br]
            [flupot.dom :as dom]))

You can use the brutha.core/mount function to attach a React element to a DOM node.

(def app (js/document.getElementById "app"))

(br/mount (dom/p "Hello World") app)

When you want to update, just call the mount function again. React will efficiently work out what needs to be changed and update only those elements.

(br/mount (dom/p "Goodbye World") app)

If you want to remove the associated component from a DOM node, use the brutha.core/unmount function:

(br/unmount app)

A Brutha component is a pure function that takes in an immutable data structure, and returns a React element. The most straightforward way to write a component is to pass a function to brutha.core/component:

(def unixtime
  (br/component (fn [date] (dom/p (str (.getTime date))))))

(br/mount (unixtime (js/Date.)) app)

By wrapping the function in a component, React knows only to update the DOM when the value passed to the function changes.

For debugging purposes, particularly when working with React Developer Tools, it often helps to give a component a display name by passing an extra argument when creating the component.

(def unixtime
  (br/component 'UnixTime (fn [date] (dom/p (str (.getTime date))))))

When using the same component multiple times with a collection of data, it's important to give React a key to identify the component. You can do this by passing a :key option to the component:

(foo-component data {:key (:id data)})

Sometimes it's useful to know when a component is mounted onto the DOM. Brutha supports this too. Instead of supplying a function to component, you can supply a reified type:

(def noisy-component
  (br/component
   (reify
     br/IShouldUpdate
     (should-update? [_ a b]
       (not= a b))

     br/IWillMount
     (will-mount [_ value]
       (js/console.log "will-mount"))

     br/IDidMount
     (did-mount [_ value dom-node]
       (js/console.log "did-mount"))

     br/IWillUpdate
     (will-update [_ value next-value dom-node]
       (js/console.log "will-update"))

     br/IDidUpdate
     (did-update [_ value prev-value dom-node]
       (js/console.log "did-update"))

     br/IWillUnmount
     (will-unmount [_ value dom-node]
       (js/console.log "will-unmount"))

     br/IRender
     (render [_ value]
       (dom/p "Hello World")))))

A component is mounted once, and updated many times. The update methods will not be called on the initial render.

License

Copyright © 2016 James Reeves

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.