Describe new features since first alpha in news050.cljs

This commit is contained in:
Dan Holmsand 2015-03-11 17:50:33 +01:00
parent 60c074b633
commit d4a595e577
2 changed files with 162 additions and 14 deletions

View File

@ -7,11 +7,22 @@
[reagentdemo.common :as common :refer [demo-component]])) [reagentdemo.common :as common :refer [demo-component]]))
(def url "news/news050.html") (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 (def ns-src (s/syntaxed "(ns example
(:require [reagent.core :as r :refer [atom]]))")) (: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] (defn input [prompt val]
[:div [:div
prompt prompt
@ -28,15 +39,33 @@
[input "Last name: " (r/wrap last-name [input "Last name: " (r/wrap last-name
swap! n assoc :last-name)]])) swap! n assoc :last-name)]]))
(defonce person (atom {:name
{:first-name "John" :last-name "Smith"}}))
(defn parent [] (defn parent []
[:div [:div
[:p "Current state: " (pr-str @person)] [:p "Current state: " (pr-str @person)]
[name-edit (r/wrap (:name @person) [name-edit (r/wrap (:name @person)
swap! person assoc :name)]]) 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 [] (defn integration []
[:div [:div
@ -58,21 +87,59 @@
#js{} #js{}
"world")]]) "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]}] (defn main [{:keys [summary]}]
[:div.reagent-demo [:div.reagent-demo
[:h1 [link {:href url} title]] [:h1 [link {:href url} title]]
[:div.demo-text [:div.demo-text
[:p "Lots of new features (and one breaking change) in Reagent [:p "Reagent 0.5.0 has automatic importing of React.js, two kinds
0.5.0-alpha."] of cursors, better integration of native React components, better
performance, easier integration with e.g Figwheel, and more."]
(if summary (if summary
[link {:href url [link {:href url
:class 'news-read-more} "Read more"] :class 'news-read-more} "Read more"]
[:div.demo-text [:div.demo-text
[:h2 "A new way of importing React"]
[:p new-in-alpha "Reagent now takes advantage of
ClojureScripts 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 youll 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"] [:h2 "Splitting atoms"]
[:p "Reagent now has a simple way to make reusable components [:p "Reagent now has a simple way to make reusable components
@ -95,8 +162,8 @@
[demo-component {:comp parent [demo-component {:comp parent
:src [:pre ns-src :src [:pre ns-src
(s/src-of [:input :name-edit (s/src-of [:person :input :name-edit
:person :parent])]}] :parent])]}]
[:p "Here, the " [:code "parent"] " component controls the [:p "Here, the " [:code "parent"] " component controls the
global state, and delegates editing the name global state, and delegates editing the name
@ -112,6 +179,60 @@
and that the callback function in the end must cause a ”real” and that the callback function in the end must cause a ”real”
atom to change."] 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 whats 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 doesnt 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 Reagents 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"] [:h2 "Faster rendering"]
@ -149,6 +270,29 @@
[demo-component {:comp integration [demo-component {:comp integration
:src (s/src-of [: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"] [:h2 "More equality"]
@ -165,13 +309,14 @@
[:h2 "React 0.12"] [: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 mirror the changes in API in React, some Reagent functions have
gotten new names: "] gotten new names: "]
[:ul [:ul
[:li [:code "render-component"] " is now " [:code "render"]] [: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"]]] [:li [:code "as-component"] " is now " [:code "as-element"]]]
[:p "The old names still work, though."] [:p "The old names still work, though."]
@ -188,6 +333,9 @@
e.g. the rather excellent " [:a {:href e.g. the rather excellent " [:a {:href
figwheel-link} "figwheel"] ", since " [:code "render"] " now figwheel-link} "figwheel"] ", since " [:code "render"] " now
will cause the entire component tree to update (by-passing the 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) (tools/register-page url [#'main] title)

View File

@ -9,7 +9,7 @@
(string/split src #"\n(?=[(])")) (string/split src #"\n(?=[(])"))
(defn src-defs [parts] (defn src-defs [parts]
(let [ws #"[^ \t]+"] (let [ws #"[^ \t\n]+"]
(into {} (for [x parts] (into {} (for [x parts]
[(->> x (re-seq ws) second keyword) x])))) [(->> x (re-seq ws) second keyword) x]))))