mirror of https://github.com/status-im/reagent.git
195 lines
7.1 KiB
Clojure
195 lines
7.1 KiB
Clojure
(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 doesn’t 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 isn’t 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. There’s 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 Reagent’s 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 doesn’t 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)
|