Skip to content

Commit

Permalink
Only show summaries on news page
Browse files Browse the repository at this point in the history
holmsand committed Feb 3, 2014
1 parent 1c70292 commit 445f1da
Showing 4 changed files with 133 additions and 110 deletions.
37 changes: 21 additions & 16 deletions demo/reagentdemo/news.cljs
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@
(reset! undo-list nil)
(remove-watch state ::undo-watcher))}))

(defn undo-example []
(defn undo-example [{:keys [summary]}]
(let [head "Cloact becomes Reagent: Undo is trivial"]
[:div.reagent-demo
[:h1 [link {:href undo-example} head]]
@@ -64,27 +64,32 @@
[:p "The API is otherwise unchanged, so a simple
search-and-replace should suffice."]

[:h2 "Undo the easy way"]
(if summary
[link {:href undo-example
:class 'news-read-more} "Read more"]
[:div.demo-text

[:p "To celebrate the undoing of the apparently disgusting name,
here is an example of how easy it is to add undo functionality
to Reagent components."]
[:h2 "Undo the easy way"]

[:p "It simply saves the old state whenever it changes, and
restores it when the button is clicked."]
[:p "To celebrate the undoing of the apparently disgusting
name, here is an example of how easy it is to add undo
functionality to Reagent components."]

[:p "The really nice thing about ClojureScript is that not only
is this easy and safe to do, courtesy of immutable data
structures, it is also efficient. ClojureScript figures out how
to represent ”changes” to maps and vectors efficiently, so that
you won’t have to."]

[undo-demo-cleanup]]]))
[:p "It simply saves the old state whenever it changes, and
restores it when the button is clicked."]

[:p "The really nice thing about ClojureScript is that not
only is this easy and safe to do, courtesy of immutable data
structures, it is also efficient. ClojureScript figures out
how to represent ”changes” to maps and vectors efficiently,
so that you won’t have to."]

[undo-demo-cleanup]])]]))

(defn main []
[:div
[async/main]
[undo-example]])
[async/main {:summary true}]
[undo-example {:summary true}]])

(swap! page-map assoc
"news/cloact-reagent-undo-demo.html" undo-example)
195 changes: 102 additions & 93 deletions demo/reagentdemo/news/async.cljs
Original file line number Diff line number Diff line change
@@ -87,102 +87,111 @@
[ncolors-choose]
[timing-wrapper {:component-fn palette}]]))

(defn main []
(defn main [{:keys [summary]}]
(let [om-article {:href "http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/"}]
[:div.reagent-demo
[title "Reagent: Faster by waiting"]
[:h1 [link {:href main} "Faster by waiting"]]
[:div.demo-text
[:h2 "Reagent gets async rendering"]

[:p "Reagent already separates state from components. Now they
are also separated in time."]
[:div.reagent-demo
[title "Reagent: Faster by waiting"]
[:h1 [link {:href main} "Faster by waiting"]]
[:div.demo-text
[:h2 "Reagent gets async rendering"]

[:p "Reagent already separates state from components. Now they
are also separated in time."]

[:p "From version 0.3.0, changes in application state (as
represented by " [:code "reagent.core/atom"] "s) are no longer
immediately rendered to the DOM. Instead, Reagent waits until the
browser is ready to repaint the window, and then all the changes
are rendered in one single go."]

[:p "This is good for all sorts of reasons:"]
[:ul
[:p "From version 0.3.0, changes in application state (as
represented by Reagent’s " [:code "atom"] "s) are no longer
rendered immediately to the DOM. Instead, Reagent waits until
the browser is ready to repaint the window, and then all the
changes are rendered in one single go."]

(if summary
[link {:href main
:class 'news-read-more} "Read more"]
[:div.demo-text

[:p "This is good for all sorts of reasons:"]
[:ul

[:li "Reagent doesn't have to spend time doing renderings that
no one would ever see (because changes to application state
happened faster than the browser could repaint)."]

[:li "If two or more atoms are changed simultaneously, this now
leads to only one re-rendering, and not two."]

[:li "The new code does proper batching of renderings even when
changes to atoms are done outside of event handlers (which is
great for e.g core.async users)."]

[:li "Repaints can be synced by the browser with for example CSS
transitions, because Reagent uses requestAnimationFrame to do
the batching. That makes for example animations smoother."]]

[:p "In short, Reagent renders less often, but at the right
times. For a much better description of why async rendering is
good, see David Nolen’s " [:a om-article "excellent explanation
here."]]

[:h2 "The bad news"]

[:p "Lunches in general tend to be non-free, and this is no
exception… The downside to async rendering is that you can no
longer depend on changes to atoms being immediately available in
the DOM. (Actually, you couldn’t before either, since React.js
itself does batching inside event handlers.)"]

[:p "This may make testing a bit more verbose: you now have to
call " [:code "reagent.core/flush"] " to force Reagent to
synchronize state with the DOM."]

[:h2 "An example"]

[:p "Here is an example to (hopefully) demonstrate the virtues of
async rendering. It consists of a simple color chooser (three
sliders to set the red, green and blue components of a base
color), and shows the base color + a bunch of divs in random
matching colors. As soon as the base color is changed, a new set
of random colors is shown."]

[:p "If you change one of the base color components, the base
color should change immediately, and smoothly (on my Macbook Air,
rendering takes around 2ms, with 20 colored divs showing)."]

[:p "But perhaps more interesting is to see what happens when the
updates can’t be made smoothly (because the browser simply cannot
re-render the colored divs quickly enough). On my machine, this
starts to happen if I change the number of divs shown to above
150 or so."]

[:p "As you increase the number of divs, you’ll notice that the
base color no longer changes quite so smoothly when you move the
color sliders."]

[:p "But the crucial point is that the sliders " [:strong "still
work"] ". Without async rendering, you could quickly get into a
situation where the browser hangs for a while, doing updates
corresponding to an old state. "]

[:p "With async rendering, the only thing that happens is that
the frame rate goes down."]

[:p "Btw, I find it quite impressive that React manages to change
500 divs (12 full screens worth) in slightly more than 40ms. And
even better: when I change the number of divs shown, it only
takes around 5ms to re-render the color palette (because the
individual divs don’t have to be re-rendered, divs are just added
or removed from the DOM as needed)."]]

[demo-component {:comp color-demo
:src (src-for
[:ns :timing-wrapper :base-color
:ncolors :random-colors :to-rgb
:tweak-color :reset-random-colors :color-choose
:ncolors-choose :palette :color-demo])}]]))
[:li "Reagent doesn't have to spend time doing renderings
that no one would ever see (because changes to application
state happened faster than the browser could repaint)."]

[:li "If two or more atoms are changed simultaneously, this
now leads to only one re-rendering, and not two."]

[:li "The new code does proper batching of renderings even
when changes to atoms are done outside of event
handlers (which is great for e.g core.async users)."]

[:li "Repaints can be synced by the browser with for example
CSS transitions, since Reagent uses requestAnimationFrame
to do the batching. That makes for example animations
smoother."]]

[:p "In short, Reagent renders less often, but at the right
times. For a much better description of why async rendering
is good, see David Nolen’s " [:a om-article "excellent
explanation here."]]

[:h2 "The bad news"]

[:p "Lunches in general tend to be non-free, and this is no
exception… The downside to async rendering is that you can no
longer depend on changes to atoms being immediately available
in the DOM. (Actually, you couldn’t before either, since
React.js itself does batching inside event handlers.)"]

[:p "This may make testing a bit more verbose: you now have
to call " [:code "reagent.core/flush"] " to force Reagent to
synchronize state with the DOM."]

[:h2 "An example"]

[:p "Here is an example to (hopefully) demonstrate the
virtues of async rendering. It consists of a simple color
chooser (three sliders to set the red, green and blue
components of a base color), and shows the base color + a
bunch of divs in random matching colors. As soon as the base
color is changed, a new set of random colors is shown."]

[:p "If you change one of the base color components, the base
color should change immediately, and smoothly (on my Macbook
Air, rendering takes around 2ms, with 20 colored divs
showing)."]

[:p "But perhaps more interesting is to see what happens when
the updates can’t be made smoothly (because the browser
simply cannot re-render the colored divs quickly enough). On
my machine, this starts to happen if I change the number of
divs shown to above 150 or so."]

[:p "As you increase the number of divs, you’ll notice that
the base color no longer changes quite so smoothly when you
move the color sliders."]

[:p "But the crucial point is that the sliders "
[:strong "still work"] ". Without async rendering, you could
quickly get into a situation where the browser hangs for a
while, doing updates corresponding to an old state. "]

[:p "With async rendering, the only thing that happens is
that the frame rate goes down."]

[:p "Btw, I find it quite impressive that React manages to
change 500 divs (12 full screens worth) in slightly more than
40ms. And even better: when I change the number of divs
shown, it only takes around 6ms to re-render the color
palette (because the individual divs don’t have to be
re-rendered, divs are just added or removed from the DOM as
needed)."]

[demo-component
{:comp color-demo
:src (src-for
[:ns :timing-wrapper :base-color :ncolors
:random-colors :to-rgb :tweak-color
:reset-random-colors :color-choose :ncolors-choose
:palette :color-demo])}]])]]))

(swap! page-map assoc
"news/reagent-is-async.html" main)
4 changes: 3 additions & 1 deletion demo/reagentdemo/page.cljs
Original file line number Diff line number Diff line change
@@ -74,7 +74,9 @@
:on-click (if history
(fn [e]
(.preventDefault e)
(reset! page href))
(reset! page href)
(set! (.-scrollTop (.-body js/document))
0))
identity))
children)))

7 changes: 7 additions & 0 deletions site/demo.css
Original file line number Diff line number Diff line change
@@ -75,6 +75,8 @@ ul.nav > li.brand > a {
font-family: 'HelveticaNeue-Light', 'Helvetica Neue', arial;
font-weight: normal;
line-height: 1.25em;
margin-top: 0.25em;
margin-bottom: 1em;
}

.reagent-demo > h1 > a {
@@ -155,6 +157,11 @@ ul.nav > li.brand > a {
cursor: pointer;
}

.news-read-more {
text-decoration: none;
font-size: 16px;
}

/* Color demo */

.color-plate {

0 comments on commit 445f1da

Please sign in to comment.