reagent/demo/reagentdemo/news/news050.cljs

195 lines
7.1 KiB
Plaintext
Raw Normal View History

2014-12-10 11:02:47 +00:00
(ns reagentdemo.news.news050
(:require [reagent.core :as r :refer [atom]]
[reagent.interop :refer-macros [.' .!]]
[reagent.debug :refer-macros [dbg println]]
[reagentdemo.syntax :as s :include-macros true]
[sitetools :as tools :refer [link]]
[reagentdemo.common :as common :refer [demo-component]]
[todomvc :as todomvc]))
(def url "news/news050.html")
(def title "News in 0.5.0-alpha")
(def ns-src (s/syntaxed "(ns example
(:require [reagent.core :as r :refer [atom]]))"))
(defn input [prompt val]
[:div
prompt
[:input {:value @val
:on-change #(reset! val (.-target.value %))}]])
(defn name-edit [n]
(let [{:keys [first-name last-name]} @n]
[:div
[:p "I'm editing " first-name " " last-name "."]
[input "First name: " (r/wrap first-name
swap! n assoc :first-name)]
[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 integration []
[:div
[:div.foo "Hello " [:strong "world"]]
(r/create-element "div"
#js{:className "foo"}
"Hello "
(r/create-element "strong"
#js{}
"world"))
(r/create-element "div"
#js{:className "foo"}
"Hello "
(r/as-element [:strong "world"]))
[:div.foo "Hello " (r/create-element "strong"
#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")
(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."]
(if summary
[link {:href url
:class 'news-read-more} "Read more"]
[:div.demo-text
[:h2 "Splitting atoms"]
[:p "Reagent now has a simple way to make reusable components
that edit part of a parents state: "]
[:p " The new " [:code "wrap"] "
function combines two parts a simple value, and a callback
for when that value should change into one value, that
happens to look as an atom. "]
[:p "The first argument to " [:code "wrap"] " should be the
value that will be returned by " [:code "@the-result"] "."]
[:p "The second argument should be a function, that will be
passed the new value whenever the result is changed (with
optional extra arguments to " [:code "wrap"] " prepended, as
with " [:code "partial"] ")."]
[:p "Usage can look something like this:"]
[demo-component {:comp parent
:src [:pre ns-src
(s/src-of [:input :name-edit
:person :parent])]}]
[:p "Here, the " [:code "parent"] " component controls the
global state, and delegates editing the name
to " [:code "name-edit"] ". " [:code "name-edit"] " in turn
delegates the actual input of first and last names
to " [:code "input"] "."]
[:p [:b "Note: "] "The result from " [:code "wrap"] " is just a
simple and light-weight value, that happens to look like an
atom it doesnt by itself trigger any re-renderings
like " [:code "reagent.core/atom"] " does. That means that it
is probably only useful to pass from one component to another,
and that the callback function in the end must cause a ”real”
atom to change."]
[:h2 "Faster rendering"]
[:p "Reagent used to wrap all ”native” React components in an
extra Reagent component, in order to keep track of how deep in
the component tree each component was (to make sure that
un-necessary re-renderings were avoided)."]
[:p "Now, this extra wrapper-component isnt needed anymore,
which means quite a bit faster generation of native React
elements. This will be noticeable if you generate html strings,
or if you animate a large number of components."]
[:h2 "Simple React integration"]
[:p "Since Reagent doesn't need those wrappers anymore it is
also now easier to mix native React components with Reagent
ones. Theres a new convenience
function, " [:code "reagent.core/create-element"] ", that
simply calls " [:a {:href
cel-link} [:code "React.createElement"]] ". This,
unsurprisingly, creates React elements, either from the result
of " [:code "React.createClass"] " or html tag names."]
[:p [:code "reagent.core/as-element"] " turns Reagents hiccup
forms into React elements, that can be passed to ordinary React
components. The combination of " [:code "create-element"] "
and " [:code "as-element"] " allows mixing and matching of
Reagent and React components."]
[:p "For an example, here are four different ways to achieve
the same thing:"]
[demo-component {:comp integration
:src (s/src-of [:integration])}]
[:h2 "More equality"]
[:p "Reagent used to have a rather complicated way of
determining when a component should be re-rendered in response
to changing arguments. Now the rule is much simpler: a
component will be re-rendered if the old and new arguments are
not equal (i.e. they are compared with a
simple " [:code "="] ")."]
[:p [:strong "Note: "] "This is a breaking change! It means
that you can no longer pass infinite " [:code "seq"] "s to a
component."]
[:h2 "React 0.12"]
[:p "Reagent now comes with, and requires, React 0.12.1. 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 "as-component"] " is now " [:code "as-element"]]]
[:p "The old names still work, though."]
[:p "There is also a new
function, " [:code "render-to-static-markup"] ", that works
just like render-to-string, except that it doesnt add
React-specific attributes."]
[:h2 "Easier live-programming"]
[:p "It is now easier than before to integrate Reagent with
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)."] ])]])
(tools/register-page url [#'main] title)