diff --git a/demo/reagentdemo/news/news050.cljs b/demo/reagentdemo/news/news050.cljs index fad1436..96f916f 100644 --- a/demo/reagentdemo/news/news050.cljs +++ b/demo/reagentdemo/news/news050.cljs @@ -7,11 +7,22 @@ [reagentdemo.common :as common :refer [demo-component]])) (def url "news/news050.html") -(def title "News in 0.5.0-alpha") +(def title "News in 0.5.0") + +(def new-in-alpha [:strong "New since 0.5.0-alpha: "]) (def ns-src (s/syntaxed "(ns example (:require [reagent.core :as r :refer [atom]]))")) +(def cel-link "http://facebook.github.io/react/docs/top-level-api.html#react.createelement") + +(def figwheel-link "https://github.com/bhauman/lein-figwheel") + + + +(defonce person (atom {:name + {:first-name "John" :last-name "Smith"}})) + (defn input [prompt val] [:div prompt @@ -28,15 +39,33 @@ [input "Last name: " (r/wrap last-name swap! n assoc :last-name)]])) -(defonce person (atom {:name - {:first-name "John" :last-name "Smith"}})) - (defn parent [] [:div [:p "Current state: " (pr-str @person)] [name-edit (r/wrap (:name @person) swap! person assoc :name)]]) +(defn cursor-name-edit [n] + (let [{:keys [first-name last-name]} @n] + [:div + [:p "I'm editing " first-name " " last-name "."] + + [input "First name: " (r/cursor n [:first-name])] + [input "Last name: " (r/cursor n [:last-name])]])) + +(defn cursor-parent [] + [:div + [:p "Current state: " (pr-str @person)] + [cursor-name-edit (r/cursor person [:name])]]) + +(defn person-get-set + ([k] (get-in @person k)) + ([k v] (swap! person assoc-in k v))) + +(defn get-set-parent [] + [:div + [:p "Current state: " (pr-str @person)] + [cursor-name-edit (r/cursor person-get-set [:name])]]) (defn integration [] [:div @@ -58,21 +87,59 @@ #js{} "world")]]) -(def cel-link "http://facebook.github.io/react/docs/top-level-api.html#react.createelement") -(def figwheel-link "https://github.com/bhauman/lein-figwheel") +(def div-adapter (r/adapt-react-class "div")) + +(defn adapted [] + [div-adapter {:class "foo"} + "Hello " [:strong "world"]]) + + +(defn exported [props] + [:div "Hi, " (:name props)]) + +(def react-comp (r/reactify-component exported)) + +(defn could-be-jsx [] + (r/create-element react-comp #js{:name "world"})) + (defn main [{:keys [summary]}] [:div.reagent-demo [:h1 [link {:href url} title]] [:div.demo-text - [:p "Lots of new features (and one breaking change) in Reagent - 0.5.0-alpha."] + [:p "Reagent 0.5.0 has automatic importing of React.js, two kinds + of cursors, better integration of native React components, better + performance, easier integration with e.g Figwheel, and more."] (if summary [link {:href url :class 'news-read-more} "Read more"] [:div.demo-text + [:h2 "A new way of importing React"] + + [:p new-in-alpha "Reagent now takes advantage of + ClojureScript’s new way of packaging JavaScript dependencies. + That means that you no longer have to include React in your + HTML, nor should you use " [:code ":preamble"] ". Instead, + Reagent depends on the " [:code "cljsjs/react"] " library."] + + [:p "If you want to use another version of React, you can do + that in two ways. In both cases you’ll have to + exclude " [:code "cljsjs/react"] " by using + e.g " [:code "[reagent \"0.5.0-alpha3\" :exclusions [cljsjs/react]]"] + " in the " [:code ":dependencies"] " section of your " + [:code "project.clj"] "."] + + [:p "You can then add e.g " [:code "[cljsjs/react-with-addons + \"0.12.2-4\"]"] " as a dependency. Or you can add a file + named " [:code "cljsjs/react.cljs"] ", containing + just " [:code "(ns cljsjs.react)"] ", to your project – and then + import React in some other way."] + + [:p "Reagent now requires ClojureScript 0.0-2816 or later."] + + [:h2 "Splitting atoms"] [:p "Reagent now has a simple way to make reusable components @@ -95,8 +162,8 @@ [demo-component {:comp parent :src [:pre ns-src - (s/src-of [:input :name-edit - :person :parent])]}] + (s/src-of [:person :input :name-edit + :parent])]}] [:p "Here, the " [:code "parent"] " component controls the global state, and delegates editing the name @@ -112,6 +179,60 @@ and that the callback function in the end must cause a ”real” atom to change."] + [:h2 "Cursors"] + + [:p new-in-alpha "Reagent has another way of isolating part of + a data structure in an atom: " [:code "reagent.core/cursor"] ". + Using the same state as in the previous example, usage now looks + like this:"] + + [demo-component {:comp cursor-parent + :src (s/src-of [:cursor-name-edit + :cursor-parent])}] + + [:p new-in-alpha "Cursors can now also be generalized to use + any transformation of data from and to a source atom (or many + atoms, for that matter). To use that, you pass a function + to " [:code "cursor"] " instead of an atom, as in this + example:"] + + [demo-component {:comp cursor-parent + :src (s/src-of [:person-get-set + :get-set-parent])}] + + [:p "The function passed to " [:code "cursor"] " will be called + with one argument to get data (it is passed the key, i.e the + second argument to " [:code "cursor"] "), and two arguments + when the cursor is changed (then it is passed the key and the + new value)."] + + [:p "The getter function can reference one or many Reagent + atoms (or other cursors). If the cursor is used in a component + the getter function will re-run to change the value of the + cursor just like a Reagent component does."] + + [:h3 "Values and references"] + + [:p "So what’s the difference between wraps and cursors? Why + have both?"] + + [:p "A " [:code "wrap"] " is just a value that happens to look + like an " [:code "atom"] ". It doesn’t change unless you tell + it to. It is a very lightweight combination of value and a + callback to back-propagate changes to the value. It relies only + on Reagent’s equality test + in " [:code ":should-component-update"] " to avoid unnecessary + re-rendering."] + + [:p "A " [:code "cursor"] ", on the other hand, will always be + up-to-date with the value of the source atom. In other words, + it acts a reference to part of the value of the source. + Components that " [:code "deref"] " cursors are re-rendered + automatically, in exactly the same way as if + they " [:code "deref"] " a normal Reagent atom (unnecessary + re-rendering is avoided by checking if the cursor's value has + changed using " [:code "identical?"] ")."] + [:h2 "Faster rendering"] @@ -149,6 +270,29 @@ [demo-component {:comp integration :src (s/src-of [:integration])}] + [:p new-in-alpha "If you don't need/want this kind of low-level + control over interaction with javascript React, you can also + use the new function " [:code "adapt-react-class"] ", that will + take any React class, and turn it into something that can be + called from Reagent directly. The example from above would then + become:"] + + [demo-component {:comp adapted + :src (s/src-of [:div-adapter :adapted])}] + + [:p new-in-alpha "You can also do the opposite: call Reagent + components from JavaScript React (for example from JSX). For + this purpose, you'd use another adapter + – " [:code "reactify-component"] " – like this:"] + + [demo-component {:comp could-be-jsx + :src (s/src-of [:exported :react-comp + :could-be-jsx])}] + + [:p "The " [:code "exported"] " component will be called with a + single argument: the React " [:code "props"] ", converted to a + ClojureScript " [:code "map"] "."] + [:h2 "More equality"] @@ -165,13 +309,14 @@ [:h2 "React 0.12"] - [:p "Reagent now comes with, and requires, React 0.12.1. To + [:p "Reagent now comes with, and requires, React 0.12.2. To mirror the changes in API in React, some Reagent functions have gotten new names: "] [:ul [:li [:code "render-component"] " is now " [:code "render"]] - [:li [:code "render-component-to-string"] " is now " [:code "render-to-string"]] + [:li [:code "render-component-to-string"] " is + now " [:code "render-to-string"]] [:li [:code "as-component"] " is now " [:code "as-element"]]] [:p "The old names still work, though."] @@ -188,6 +333,9 @@ e.g. the rather excellent " [:a {:href figwheel-link} "figwheel"] ", since " [:code "render"] " now will cause the entire component tree to update (by-passing the - equality checks)."] ])]]) + equality checks)."] + + [:p new-in-alpha "All the examples in the Reagent repo now uses + figwheel."]])]]) (tools/register-page url [#'main] title) diff --git a/demo/reagentdemo/syntax.clj b/demo/reagentdemo/syntax.clj index c2b2c92..4434984 100644 --- a/demo/reagentdemo/syntax.clj +++ b/demo/reagentdemo/syntax.clj @@ -9,7 +9,7 @@ (string/split src #"\n(?=[(])")) (defn src-defs [parts] - (let [ws #"[^ \t]+"] + (let [ws #"[^ \t\n]+"] (into {} (for [x parts] [(->> x (re-seq ws) second keyword) x]))))