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]]))
(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
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"]
[: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 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"]
@ -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)

View File

@ -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]))))