mirror of https://github.com/status-im/reagent.git
195 lines
7.1 KiB
Plaintext
195 lines
7.1 KiB
Plaintext
|
(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 (fn [] [main]) title)
|