GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing reagent-project.github.io — Reagent: Minimalistic React for ClojureScript Reagent: Minimalistic React for ClojureScriptIntroduction to ReagentReagent provides a minimalistic interface between ClojureScript and React. It allows you to define efficient React components using nothing but plain ClojureScript functions and data, that describe your UI using a Hiccup-like syntax. The goal of Reagent is to make it possible to define arbitrarily complex UIs using just a couple of basic concepts, and to be fast enough by default that you rarely have to think about performance. A very basic Reagent component may look something like this: hide ExampleI am a component! I have bold and red text. Source(r/defc simple-component [] [:div [:p "I am a component!"] [:p.someclass "I have " [:strong "bold"] [:span {:style {:color "red"}} " and red "] "text."]]) You can build new components using other components as building blocks. Like this: hide ExampleI include simple-component. I am a component! I have bold and red text. Source(r/defc simple-parent [] [:div [:p "I include simple-component."] [simple-component]]) Data is passed to child components using plain old Clojure data types. Like this: hide ExampleHello, world! Source(r/defc hello-component [name] [:p "Hello, " name "!"]) (r/defc say-hello [] [hello-component "world"]) Note: In the example above, Here is another example that shows items in a hide ExampleHere is a list:
Source(r/defc lister [items] [:ul (for [item items] ^{:key item} [:li "Item " item])]) (r/defc lister-user [] [:div "Here is a list:" [lister (range 3)]]) Note: The Managing state in ReagentThe easiest way to manage state in Reagent is to use Reagent’s
own version of Let’s demonstrate that with a simple example: hide ExampleThe atom click-count has value: 0. Source(ns example (:require [reagent.core :as r]))(def click-count (r/atom 0)) (r/defc counting-component [] [:div "The atom " [:code "click-count"] " has value: " @click-count ". " [:input {:type "button" :value "Click me!" :on-click #(swap! click-count inc)}]]) Sometimes you may want to maintain state locally in a
component. That is easy to do with an Here is an example of that, where we call hide ExampleSeconds Elapsed: 0 Source(defn timer-component [] (let [seconds-elapsed (r/atom 0)] (fn [] (js/setTimeout #(swap! seconds-elapsed inc) 1000) [:div "Seconds Elapsed: " @seconds-elapsed]))) The previous example also uses another feature of Reagent: a component function can return another function, that is used to do the actual rendering. This function is called with the same arguments as the first one. This allows you to perform some setup of newly created components without resorting to React’s lifecycle events. By simply passing an hide ExampleThe value is now: foo Change it here: Source(ns example (:require [reagent.core :as r]))(r/defc atom-input [value] [:input {:type "text" :value @value :on-change #(reset! value (-> % .-target .-value))}]) (defn shared-state [] (let [val (r/atom "foo")] (fn [] [:div [:p "The value is now: " @val] [:p "Change it here: " [atom-input val]]]))) Note: Component functions can be called with any arguments – as long as they are immutable. You could use mutable objects as well, but then you have to make sure that the component is updated when your data changes. Reagent assumes by default that two objects are equal if they are the same object. Essential APIReagent supports most of React’s API, but there is really only
one entry-point that is necessary for most applications: It takes two arguments: a component, and a DOM node. For example, splashing the very first example all over the page would look like this: Source(ns example (:require [reagent.dom :as rdom]))(r/defc simple-component [] [:div [:p "I am a component!"] [:p.someclass "I have " [:strong "bold"] [:span {:style {:color "red"}} " and red "] "text."]]) Putting it all togetherHere is a slightly less contrived example: a simple BMI calculator. Data is kept in a single hide ExampleBMI calculatorHeight: 180cm Weight: 80kg BMI: 24 normal Source(ns example (:require [reagent.core :as r]))(defn calc-bmi [{:keys [height weight bmi] :as data}] (let [h (/ height 100)] (if (nil? bmi) (assoc data :bmi (/ weight (* h h))) (assoc data :weight (* bmi h h))))) (def bmi-data (r/atom (calc-bmi {:height 180 :weight 80}))) (r/defc slider [param value min max invalidates] [:input {:type "range" :value value :min min :max max :style {:width "100%"} :on-change (fn [e] (let [new-value (js/parseInt (.. e -target -value))] (swap! bmi-data (fn [data] (-> data (assoc param new-value) (dissoc invalidates) calc-bmi)))))}]) (r/defc bmi-component [] (let [{:keys [weight height bmi]} @bmi-data [color diagnose] (cond (< bmi 18.5) ["orange" "underweight"] (< bmi 25) ["inherit" "normal"] (< bmi 30) ["orange" "overweight"] :else ["red" "obese"])] [:div [:h3 "BMI calculator"] [:div "Height: " (int height) "cm" [slider :height height 100 220 :bmi]] [:div "Weight: " (int weight) "kg" [slider :weight weight 30 150 :bmi]] [:div "BMI: " (int bmi) " " [:span {:style {:color color}} diagnose] [slider :bmi bmi 10 50 :weight]]])) PerformanceReact itself is very fast, and so is Reagent. In fact, Reagent will be even faster than plain React a lot of the time, thanks to optimizations made possible by ClojureScript. Mounted components are only re-rendered when their parameters
have changed. The change could come from a deref’ed All of these are checked for changes with All this means that you simply won’t have to care about performance most of the time. Just define your UI however you like – it will be fast enough. There are a couple of situations that you might have to care
about, though. If you give Reagent a big But again, in general you should just trust that React and Reagent will be fast enough. This very page is composed of a single Reagent component with thousands of child components (every single parenthesis etc in the code examples is a separate component), and yet the page can be updated many times every second without taxing the browser the slightest. Incidentally, this page also uses another React trick: the
entire page is pre-rendered using Node, and ![]() |
| You are visitor 01402520 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |