diff --git a/blog/2013/06/02/jsfiddle-integration.html b/blog/2013/06/02/jsfiddle-integration.html index 9ab2b34200..3fde4fee76 100644 --- a/blog/2013/06/02/jsfiddle-integration.html +++ b/blog/2013/06/02/jsfiddle-integration.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/06/05/why-react.html b/blog/2013/06/05/why-react.html index 0022aa0c62..441bb2af6b 100644 --- a/blog/2013/06/05/why-react.html +++ b/blog/2013/06/05/why-react.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/06/12/community-roundup.html b/blog/2013/06/12/community-roundup.html index 2efd902dd2..41fb5338c0 100644 --- a/blog/2013/06/12/community-roundup.html +++ b/blog/2013/06/12/community-roundup.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/06/19/community-roundup-2.html b/blog/2013/06/19/community-roundup-2.html index 38e5cbd54b..146743a385 100644 --- a/blog/2013/06/19/community-roundup-2.html +++ b/blog/2013/06/19/community-roundup-2.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/06/21/react-v0-3-3.html b/blog/2013/06/21/react-v0-3-3.html index a33c239ac1..e148676a6c 100644 --- a/blog/2013/06/21/react-v0-3-3.html +++ b/blog/2013/06/21/react-v0-3-3.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/06/27/community-roundup-3.html b/blog/2013/06/27/community-roundup-3.html index 853b5b911e..6398c1541f 100644 --- a/blog/2013/06/27/community-roundup-3.html +++ b/blog/2013/06/27/community-roundup-3.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/02/react-v0-4-autobind-by-default.html b/blog/2013/07/02/react-v0-4-autobind-by-default.html index 2e9ff7560a..e0ebf5c481 100644 --- a/blog/2013/07/02/react-v0-4-autobind-by-default.html +++ b/blog/2013/07/02/react-v0-4-autobind-by-default.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/03/community-roundup-4.html b/blog/2013/07/03/community-roundup-4.html index b582b3f2db..313bc7705d 100644 --- a/blog/2013/07/03/community-roundup-4.html +++ b/blog/2013/07/03/community-roundup-4.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html b/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html index 8bd81b9922..649d0a1098 100644 --- a/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html +++ b/blog/2013/07/11/react-v0-4-prop-validation-and-default-values.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/17/react-v0-4-0.html b/blog/2013/07/17/react-v0-4-0.html index 126346bd03..31264b4b06 100644 --- a/blog/2013/07/17/react-v0-4-0.html +++ b/blog/2013/07/17/react-v0-4-0.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/23/community-roundup-5.html b/blog/2013/07/23/community-roundup-5.html index 8d675442ff..33be9ac560 100644 --- a/blog/2013/07/23/community-roundup-5.html +++ b/blog/2013/07/23/community-roundup-5.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/26/react-v0-4-1.html b/blog/2013/07/26/react-v0-4-1.html index e9a8930835..4dacc04d78 100644 --- a/blog/2013/07/26/react-v0-4-1.html +++ b/blog/2013/07/26/react-v0-4-1.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/07/30/use-react-and-jsx-in-ruby-on-rails.html b/blog/2013/07/30/use-react-and-jsx-in-ruby-on-rails.html index 8a86c6f306..929c180db6 100644 --- a/blog/2013/07/30/use-react-and-jsx-in-ruby-on-rails.html +++ b/blog/2013/07/30/use-react-and-jsx-in-ruby-on-rails.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/08/05/community-roundup-6.html b/blog/2013/08/05/community-roundup-6.html index b4e7871ab1..cd67dbdb55 100644 --- a/blog/2013/08/05/community-roundup-6.html +++ b/blog/2013/08/05/community-roundup-6.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/08/19/use-react-and-jsx-in-python-applications.html b/blog/2013/08/19/use-react-and-jsx-in-python-applications.html index 32332feb10..4f6b53aed0 100644 --- a/blog/2013/08/19/use-react-and-jsx-in-python-applications.html +++ b/blog/2013/08/19/use-react-and-jsx-in-python-applications.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/08/26/community-roundup-7.html b/blog/2013/08/26/community-roundup-7.html index fd7556525b..2c7848e383 100644 --- a/blog/2013/08/26/community-roundup-7.html +++ b/blog/2013/08/26/community-roundup-7.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/09/24/community-roundup-8.html b/blog/2013/09/24/community-roundup-8.html index a263b2c3ea..a7f1daa52b 100644 --- a/blog/2013/09/24/community-roundup-8.html +++ b/blog/2013/09/24/community-roundup-8.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/10/03/community-roundup-9.html b/blog/2013/10/03/community-roundup-9.html index f96ed6b3d3..d808d5b7cc 100644 --- a/blog/2013/10/03/community-roundup-9.html +++ b/blog/2013/10/03/community-roundup-9.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/10/16/react-v0.5.0.html b/blog/2013/10/16/react-v0.5.0.html index 704a0a6e01..7ced09e933 100644 --- a/blog/2013/10/16/react-v0.5.0.html +++ b/blog/2013/10/16/react-v0.5.0.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/10/29/react-v0-5-1.html b/blog/2013/10/29/react-v0-5-1.html index ee491bdc0e..039db02995 100644 --- a/blog/2013/10/29/react-v0-5-1.html +++ b/blog/2013/10/29/react-v0-5-1.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/11/05/thinking-in-react.html b/blog/2013/11/05/thinking-in-react.html index 43d7f8b671..ee5cabfd65 100644 --- a/blog/2013/11/05/thinking-in-react.html +++ b/blog/2013/11/05/thinking-in-react.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/11/06/community-roundup-10.html b/blog/2013/11/06/community-roundup-10.html index 04dad53f1d..9ca7f01903 100644 --- a/blog/2013/11/06/community-roundup-10.html +++ b/blog/2013/11/06/community-roundup-10.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/11/18/community-roundup-11.html b/blog/2013/11/18/community-roundup-11.html index ce65b20d00..dd19ea34fc 100644 --- a/blog/2013/11/18/community-roundup-11.html +++ b/blog/2013/11/18/community-roundup-11.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/12/18/react-v0.5.2-v0.4.2.html b/blog/2013/12/18/react-v0.5.2-v0.4.2.html index b58384fef3..a8b0bb6441 100644 --- a/blog/2013/12/18/react-v0.5.2-v0.4.2.html +++ b/blog/2013/12/18/react-v0.5.2-v0.4.2.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/12/19/react-v0.8.0.html b/blog/2013/12/19/react-v0.8.0.html index 53eef16e0d..28ed469f4f 100644 --- a/blog/2013/12/19/react-v0.8.0.html +++ b/blog/2013/12/19/react-v0.8.0.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/12/23/community-roundup-12.html b/blog/2013/12/23/community-roundup-12.html index 08e7ba4a84..d89f53b18b 100644 --- a/blog/2013/12/23/community-roundup-12.html +++ b/blog/2013/12/23/community-roundup-12.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2013/12/30/community-roundup-13.html b/blog/2013/12/30/community-roundup-13.html index bf9b3622d7..f4de97050a 100644 --- a/blog/2013/12/30/community-roundup-13.html +++ b/blog/2013/12/30/community-roundup-13.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/01/02/react-chrome-developer-tools.html b/blog/2014/01/02/react-chrome-developer-tools.html index 3d2274295c..d6cb834113 100644 --- a/blog/2014/01/02/react-chrome-developer-tools.html +++ b/blog/2014/01/02/react-chrome-developer-tools.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/01/06/community-roundup-14.html b/blog/2014/01/06/community-roundup-14.html index 8a4a237f94..a2185af934 100644 --- a/blog/2014/01/06/community-roundup-14.html +++ b/blog/2014/01/06/community-roundup-14.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/02/05/community-roundup-15.html b/blog/2014/02/05/community-roundup-15.html index edba0c4415..dbe47e8795 100644 --- a/blog/2014/02/05/community-roundup-15.html +++ b/blog/2014/02/05/community-roundup-15.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/02/15/community-roundup-16.html b/blog/2014/02/15/community-roundup-16.html index 3875d14824..0ae9072bb2 100644 --- a/blog/2014/02/15/community-roundup-16.html +++ b/blog/2014/02/15/community-roundup-16.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/02/16/react-v0.9-rc1.html b/blog/2014/02/16/react-v0.9-rc1.html index f795eceb26..88750112e8 100644 --- a/blog/2014/02/16/react-v0.9-rc1.html +++ b/blog/2014/02/16/react-v0.9-rc1.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/02/20/react-v0.9.html b/blog/2014/02/20/react-v0.9.html index cc75e8d67b..eb52f1ba78 100644 --- a/blog/2014/02/20/react-v0.9.html +++ b/blog/2014/02/20/react-v0.9.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/02/24/community-roundup-17.html b/blog/2014/02/24/community-roundup-17.html index f55501ca94..e5f419ff1f 100644 --- a/blog/2014/02/24/community-roundup-17.html +++ b/blog/2014/02/24/community-roundup-17.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/03/14/community-roundup-18.html b/blog/2014/03/14/community-roundup-18.html index 82dbb98fab..608391bc4b 100644 --- a/blog/2014/03/14/community-roundup-18.html +++ b/blog/2014/03/14/community-roundup-18.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/03/19/react-v0.10-rc1.html b/blog/2014/03/19/react-v0.10-rc1.html index 383af05a76..e06474f052 100644 --- a/blog/2014/03/19/react-v0.10-rc1.html +++ b/blog/2014/03/19/react-v0.10-rc1.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/03/21/react-v0.10.html b/blog/2014/03/21/react-v0.10.html index c35482324b..55a1880871 100644 --- a/blog/2014/03/21/react-v0.10.html +++ b/blog/2014/03/21/react-v0.10.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/03/28/the-road-to-1.0.html b/blog/2014/03/28/the-road-to-1.0.html index 2aaa7b9966..0feac259d7 100644 --- a/blog/2014/03/28/the-road-to-1.0.html +++ b/blog/2014/03/28/the-road-to-1.0.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/04/04/reactnet.html b/blog/2014/04/04/reactnet.html index 13096a16c6..7825f8e2b8 100644 --- a/blog/2014/04/04/reactnet.html +++ b/blog/2014/04/04/reactnet.html @@ -63,6 +63,8 @@

Recent posts

diff --git a/blog/2014/05/06/flux.html b/blog/2014/05/06/flux.html new file mode 100644 index 0000000000..37e4962d76 --- /dev/null +++ b/blog/2014/05/06/flux.html @@ -0,0 +1,146 @@ + + + + + + + React | Flux: An Application Architecture for React + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+

Flux: An Application Architecture for React

+

May 6, 2014 by Bill Fisher and Jing Chen

+ +
+ +
+

We recently spoke at one of f8's breakout session about Flux, a data flow architecture that works well with React. Check out the video here:

+ +
+ +

To summarize, Flux works well for us because the single directional data flow makes it easy to understand and modify an application as it becomes more complicated. We found that two-way data bindings lead to cascading updates, where changing one data model led to another data model updating, making it very difficult to predict what would change as the result of a single user interaction.

+ +

In Flux, the Dispatcher is a singleton that directs the flow of data and ensures that updates do not cascade. As an application grows, the Dispatcher becomes more vital, as it can also manage dependencies between stores by invoking the registered callbacks in a specific order.

+ +

When a user interacts with a React view, the view sends an action (usually represented as a JavaScript object with some fields) through the dispatcher, which notifies the various stores that hold the application's data and business logic. When the stores change state, they notify the views that something has updated. This works especially well with React's declarative model, which allows the stores to send updates without specifying how to transition views between states.

+ +

Flux is more of a pattern than a formal framework, so you can start using Flux immediately without a lot of new code. An example of this architecture is available, along with more detailed documentation and a tutorial. Look for more examples to come in the future.

+ +
+ +
+
+
+ + + +
+
+ + + + diff --git a/blog/all.html b/blog/all.html index 507b6b58b3..a1c62ac370 100644 --- a/blog/all.html +++ b/blog/all.html @@ -61,6 +61,8 @@

All Posts

+

Flux: An Application Architecture for React on May 6, 2014 by Bill Fisher and Jing Chen

+

Use React and JSX in ASP.NET MVC on April 4, 2014 by Daniel Lo Nigro

The Road to 1.0 on March 28, 2014 by Paul O'Shannessy

diff --git a/blog/index.html b/blog/index.html index 795b5d29de..0a6e55f943 100644 --- a/blog/index.html +++ b/blog/index.html @@ -63,6 +63,8 @@

Recent posts

@@ -90,6 +90,26 @@
+
+

Flux: An Application Architecture for React

+

May 6, 2014 by Bill Fisher and Jing Chen

+
+
+

We recently spoke at one of f8's breakout session about Flux, a data flow architecture that works well with React. Check out the video here:

+ +
+ +

To summarize, Flux works well for us because the single directional data flow makes it easy to understand and modify an application as it becomes more complicated. We found that two-way data bindings lead to cascading updates, where changing one data model led to another data model updating, making it very difficult to predict what would change as the result of a single user interaction.

+ +

In Flux, the Dispatcher is a singleton that directs the flow of data and ensures that updates do not cascade. As an application grows, the Dispatcher becomes more vital, as it can also manage dependencies between stores by invoking the registered callbacks in a specific order.

+ +

When a user interacts with a React view, the view sends an action (usually represented as a JavaScript object with some fields) through the dispatcher, which notifies the various stores that hold the application's data and business logic. When the stores change state, they notify the views that something has updated. This works especially well with React's declarative model, which allows the stores to send updates without specifying how to transition views between states.

+ +

Flux is more of a pattern than a formal framework, so you can start using Flux immediately without a lot of new code. An example of this architecture is available, along with more detailed documentation and a tutorial. Look for more examples to come in the future.

+ +
+
+

Use React and JSX in ASP.NET MVC

April 4, 2014 by Daniel Lo Nigro

@@ -314,89 +334,6 @@ Minified build for production: -

Community Round-up #18

-

March 14, 2014 by Jonas Gebhardt

-
-
-

In this Round-up, we are taking a few closer looks at React's interplay with different frameworks and architectures.

-

"Little framework BIG splash" #

-

Let's start with yet another refreshing introduction to React: Craig Savolainen (@maedhr) walks through some first steps, demonstrating how to build a Google Maps component using React.

-

Architecting your app with react #

-

Brandon Konkle (@bkonkle) -Architecting your app with react -We're looking forward to part 2!

- -
-

React is not a full MVC framework, and this is actually one of its strengths. Many who adopt React choose to do so alongside their favorite MVC framework, like Backbone. React has no opinions about routing or syncing data, so you can easily use your favorite tools to handle those aspects of your frontend application. You'll often see React used to manage specific parts of an application's UI and not others. React really shines, however, when you fully embrace its strategies and make it the core of your application's interface.

- -

Read the full article...

-
-

React vs. async DOM manipulation #

-

Eliseu Monar (@eliseumds)'s post "ReactJS vs async concurrent rendering" is a great example of how React quite literally renders a whole array of common web development work(arounds) obsolete.

-

React, Scala and the Play Framework #

-

Matthias Nehlsen wrote a detailed introductory piece on React and the Play Framework, including a helpful architectural diagram of a typical React app.

- -

Nehlsen's React frontend is the second implementation of his chat application's frontend, following an AngularJS version. Both implementations are functionally equivalent and offer some perspective on differences between the two frameworks.

- -

In another article, he walks us through the process of using React with scala.js to implement app-wide undo functionality.

- -

Also check out his talk at Ping Conference 2014, in which he walks through a lot of the previously content in great detail.

-

React and Backbone #

-

The folks over at Venmo are using React in conjunction with Backbone. -Thomas Boyt (@thomasaboyt) wrote this detailed piece about why React and Backbone are "a fantastic pairing".

-

React vs. Ember #

-

Eric Berry (@coderberry) developed Ember equivalents for some of the official React examples. Read his post for a side-by-side comparison of the respective implementations: "Facebook React vs. Ember".

-

React and plain old HTML #

-

Daniel Lo Nigro (@Daniel15) created React-Magic, which leverages React to ajaxify plain old html pages and even allows CSS transitions between pageloads.

- -
-

React-Magic intercepts all navigation (link clicks and form posts) and loads the requested page via an AJAX request. React is then used to "diff" the old HTML with the new HTML, and only update the parts of the DOM that have been changed.

- -

Check out the project on GitHub...

-
- -

On a related note, Reactize by Ross Allen (@ssorallen) is a similarly awesome project: A wrapper for Rails' Turbolinks, which seems to have inspired John Lynch (@johnrlynch) to then create a server-rendered version using the JSX transformer in Rails middleware.

-

React and Object.observe #

-

Check out François de Campredon's implementation of TodoMVC based on React and ES6's Object.observe.

-

React and Angular #

-

Ian Bicking (@ianbicking) of Mozilla Labs explains why he "decided to go with React instead of Angular.js".

-

ng-React Update #

-

David Chang works through some performance improvements of his ngReact project. His post "ng-React Update - React 0.9 and Angular Track By" includes some helpful advice on boosting render performance for Angular components.

- -
-

Angular gives you a ton of functionality out of the box - a full MV* framework - and I am a big fan, but I'll admit that you need to know how to twist the right knobs to get performance.

- -

That said, React gives you a very strong view component out of the box with the performance baked right in. Try as I did, I couldn't actually get it any faster. So pretty impressive stuff.

- -

Read the full post...

-
- -

React was also recently mentioned at ng-conf, where the Angular team commented on React's concept of the virtual DOM:

- - -

React and Web Components #

-

Jonathan Krause (@jonykrause) offers his thoughts regarding parallels between React and Web Components, highlighting the value of React's ability to render pages on the server practically for free.

-

Immutable React #

-

Peter Hausel shows how to build a Wikipedia auto-complete demo based on immutable data structures (similar to mori), really taking advantage of the framework's one-way reactive data binding:

- -
-

Its truly reactive design makes DOM updates finally sane and when combined with persistent data structures one can experience JavaScript development like it was never done before.

- -

Read the full post

-
-

D3 and React #

-

Ben Smith built some great SVG-based charting components using a little less of D3 and a little more of React: D3 and React - the future of charting components?

-

Om and React #

-

Josh Haberman (@joshhaberman) discusses performance differences between React, Om and traditional MVC frameworks in "A closer look at OM vs React performance".

- -

Speaking of Om: Omchaya by Sean Grove (@sgrove) is a neat Cljs/Om example project.

-

Random Tweets #

-
- -
-
- @@ -90,6 +90,89 @@
+
+

Community Round-up #18

+

March 14, 2014 by Jonas Gebhardt

+
+
+

In this Round-up, we are taking a few closer looks at React's interplay with different frameworks and architectures.

+

"Little framework BIG splash" #

+

Let's start with yet another refreshing introduction to React: Craig Savolainen (@maedhr) walks through some first steps, demonstrating how to build a Google Maps component using React.

+

Architecting your app with react #

+

Brandon Konkle (@bkonkle) +Architecting your app with react +We're looking forward to part 2!

+ +
+

React is not a full MVC framework, and this is actually one of its strengths. Many who adopt React choose to do so alongside their favorite MVC framework, like Backbone. React has no opinions about routing or syncing data, so you can easily use your favorite tools to handle those aspects of your frontend application. You'll often see React used to manage specific parts of an application's UI and not others. React really shines, however, when you fully embrace its strategies and make it the core of your application's interface.

+ +

Read the full article...

+
+

React vs. async DOM manipulation #

+

Eliseu Monar (@eliseumds)'s post "ReactJS vs async concurrent rendering" is a great example of how React quite literally renders a whole array of common web development work(arounds) obsolete.

+

React, Scala and the Play Framework #

+

Matthias Nehlsen wrote a detailed introductory piece on React and the Play Framework, including a helpful architectural diagram of a typical React app.

+ +

Nehlsen's React frontend is the second implementation of his chat application's frontend, following an AngularJS version. Both implementations are functionally equivalent and offer some perspective on differences between the two frameworks.

+ +

In another article, he walks us through the process of using React with scala.js to implement app-wide undo functionality.

+ +

Also check out his talk at Ping Conference 2014, in which he walks through a lot of the previously content in great detail.

+

React and Backbone #

+

The folks over at Venmo are using React in conjunction with Backbone. +Thomas Boyt (@thomasaboyt) wrote this detailed piece about why React and Backbone are "a fantastic pairing".

+

React vs. Ember #

+

Eric Berry (@coderberry) developed Ember equivalents for some of the official React examples. Read his post for a side-by-side comparison of the respective implementations: "Facebook React vs. Ember".

+

React and plain old HTML #

+

Daniel Lo Nigro (@Daniel15) created React-Magic, which leverages React to ajaxify plain old html pages and even allows CSS transitions between pageloads.

+ +
+

React-Magic intercepts all navigation (link clicks and form posts) and loads the requested page via an AJAX request. React is then used to "diff" the old HTML with the new HTML, and only update the parts of the DOM that have been changed.

+ +

Check out the project on GitHub...

+
+ +

On a related note, Reactize by Ross Allen (@ssorallen) is a similarly awesome project: A wrapper for Rails' Turbolinks, which seems to have inspired John Lynch (@johnrlynch) to then create a server-rendered version using the JSX transformer in Rails middleware.

+

React and Object.observe #

+

Check out François de Campredon's implementation of TodoMVC based on React and ES6's Object.observe.

+

React and Angular #

+

Ian Bicking (@ianbicking) of Mozilla Labs explains why he "decided to go with React instead of Angular.js".

+

ng-React Update #

+

David Chang works through some performance improvements of his ngReact project. His post "ng-React Update - React 0.9 and Angular Track By" includes some helpful advice on boosting render performance for Angular components.

+ +
+

Angular gives you a ton of functionality out of the box - a full MV* framework - and I am a big fan, but I'll admit that you need to know how to twist the right knobs to get performance.

+ +

That said, React gives you a very strong view component out of the box with the performance baked right in. Try as I did, I couldn't actually get it any faster. So pretty impressive stuff.

+ +

Read the full post...

+
+ +

React was also recently mentioned at ng-conf, where the Angular team commented on React's concept of the virtual DOM:

+ + +

React and Web Components #

+

Jonathan Krause (@jonykrause) offers his thoughts regarding parallels between React and Web Components, highlighting the value of React's ability to render pages on the server practically for free.

+

Immutable React #

+

Peter Hausel shows how to build a Wikipedia auto-complete demo based on immutable data structures (similar to mori), really taking advantage of the framework's one-way reactive data binding:

+ +
+

Its truly reactive design makes DOM updates finally sane and when combined with persistent data structures one can experience JavaScript development like it was never done before.

+ +

Read the full post

+
+

D3 and React #

+

Ben Smith built some great SVG-based charting components using a little less of D3 and a little more of React: D3 and React - the future of charting components?

+

Om and React #

+

Josh Haberman (@joshhaberman) discusses performance differences between React, Om and traditional MVC frameworks in "A closer look at OM vs React performance".

+ +

Speaking of Om: Omchaya by Sean Grove (@sgrove) is a neat Cljs/Om example project.

+

Random Tweets #

+
+ +
+
+

Community Round-up #17

February 24, 2014 by Jonas Gebhardt

@@ -473,118 +556,6 @@ Minified build for production: -

Community Round-up #15

-

February 5, 2014 by Jonas Gebhardt

-
-
-

Interest in React seems to have surged ever since David Nolen (@swannodette)'s introduction of Om in his post "The Future of Javascript MVC Frameworks".

- -

In this React Community Round-up, we are taking a closer look at React from a functional programming perspective.

-

"React: Another Level of Indirection" #

-

To start things off, Eric Normand (@ericnormand) of LispCast makes the case for React from a general functional programming standpoint and explains how React's "Virtual DOM provides the last piece of the Web Frontend Puzzle for ClojureScript".

- -
-

The Virtual DOM is an indirection mechanism that solves the difficult problem of DOM programming: how to deal with incremental changes to a stateful tree structure. By abstracting away the statefulness, the Virtual DOM turns the real DOM into an immediate mode GUI, which is perfect for functional programming.

- -

Read the full post...

-
-

Reagent: Minimalistic React for ClojureScript #

-

Dan Holmsand (@holmsand) created Reagent, a simplistic ClojureScript API to React.

- -
-

It allows you to define efficient React components using nothing but plain ClojureScript functions and data, that describe your UI using a Hiccup-like syntax.

- -

The goal of Reagent is to make it possible to define arbitrarily complex UIs using just a couple of basic concepts, and to be fast enough by default that you rarely have to care about performance.

- -

Check it out on Github...

-
-

Functional DOM programming #

-

React's one-way data-binding naturally lends itself to a functional programming approach. Facebook's Pete Hunt (@floydophone) explores how one would go about writing web apps in a functional manner. Spoiler alert:

- -
-

This is React. It’s not about templates, or data binding, or DOM manipulation. It’s about using functional programming with a virtual DOM representation to build ambitious, high-performance apps with JavaScript.

- -

Read the full post...

-
- -

Pete also explains this in detail at his #MeteorDevShop talk (about 30 Minutes):

- - -

Kioo: Separating markup and logic #

-

Creighton Kirkendall created Kioo, which adds Enlive-style templating to React. HTML templates are separated from the application logic. Kioo comes with separate examples for both Om and Reagent.

- -

A basic example from github:

-
<!DOCTYPE html>
-<html lang="en">
-  <body>
-    <header>
-      <h1>Header placeholder</h1>
-      <ul id="navigation">
-        <li class="nav-item"><a href="#">Placeholder</a></li>
-      </ul>
-    </header>
-    <div class="content">place holder</div>
-  </body>
-</html>
-
...
-
-(defn my-nav-item [[caption func]]
-  (kioo/component "main.html" [:.nav-item]
-    {[:a] (do-> (content caption)
-                (set-attr :onClick func))}))
-
-(defn my-header [heading nav-elms]
-  (kioo/component "main.html" [:header]
-    {[:h1] (content heading)
-     [:ul] (content (map my-nav-item nav-elms))}))
-
-(defn my-page [data]
-  (kioo/component "main.html"
-    {[:header] (substitute (my-header (:heading data)
-                                      (:navigation data)))
-     [:.content] (content (:content data))}))
-
-(def app-state (atom {:heading    "main"
-                      :content    "Hello World"
-                      :navigation [["home" #(js/alert %)]
-                                   ["next" #(js/alert %)]]}))
-
-(om/root app-state my-page (.-body js/document))
-

Om #

-

In an interview with David Nolen, Tom Coupland (@tcoupland) of InfoQ provides a nice summary of recent developments around Om ("Om: Enhancing Facebook's React with Immutability").

- -
-

David [Nolen]: I think people are starting to see the limitations of just JavaScript and jQuery and even more structured solutions like Backbone, Angular, Ember, etc. React is a fresh approach to the DOM problem that seems obvious in hindsight.

- -

Read the full interview...

-
-

A slice of React, ClojureScript and Om #

-

Fredrik Dyrkell (@lexicallyscoped) rewrote part of the React tutorial in both ClojureScript and Om, along with short, helpful explanations.

- -
-

React has sparked a lot of interest in the Clojure community lately [...]. At the very core, React lets you build up your DOM representation in a functional fashion by composing pure functions and you have a simple building block for everything: React components.

- -

Read the full post...

-
- -

In a separate post, Dyrkell breaks down how to build a binary clock component in Om.

- -

[Demo] [Code]

-

Time Travel: Implementing undo in Om #

-

David Nolen shows how to leverage immutable data structures to add global undo functionality to an app – using just 13 lines of ClojureScript.

-

A Step-by-Step Om Walkthrough #

-

Josh Lehman took the time to create an extensive step-by-step walkthrough of the React tutorial in Om. The well-documented source is on github.

-

Omkara #

-

brendanyounger created omkara, a starting point for ClojureScript web apps based on Om/React. It aims to take advantage of server-side rendering and comes with a few tips on getting started with Om/React projects.

-

Om Experience Report #

-

Adam Solove (@asolove) dives a little deeper into Om, React and ClojureScript. He shares some helpful tips he gathered while building his CartoCrayon prototype.

-

Not-so-random Tweet #

-
- -
-
- @@ -90,6 +90,118 @@
+
+

Community Round-up #15

+

February 5, 2014 by Jonas Gebhardt

+
+
+

Interest in React seems to have surged ever since David Nolen (@swannodette)'s introduction of Om in his post "The Future of Javascript MVC Frameworks".

+ +

In this React Community Round-up, we are taking a closer look at React from a functional programming perspective.

+

"React: Another Level of Indirection" #

+

To start things off, Eric Normand (@ericnormand) of LispCast makes the case for React from a general functional programming standpoint and explains how React's "Virtual DOM provides the last piece of the Web Frontend Puzzle for ClojureScript".

+ +
+

The Virtual DOM is an indirection mechanism that solves the difficult problem of DOM programming: how to deal with incremental changes to a stateful tree structure. By abstracting away the statefulness, the Virtual DOM turns the real DOM into an immediate mode GUI, which is perfect for functional programming.

+ +

Read the full post...

+
+

Reagent: Minimalistic React for ClojureScript #

+

Dan Holmsand (@holmsand) created Reagent, a simplistic ClojureScript API to React.

+ +
+

It allows you to define efficient React components using nothing but plain ClojureScript functions and data, that describe your UI using a Hiccup-like syntax.

+ +

The goal of Reagent is to make it possible to define arbitrarily complex UIs using just a couple of basic concepts, and to be fast enough by default that you rarely have to care about performance.

+ +

Check it out on Github...

+
+

Functional DOM programming #

+

React's one-way data-binding naturally lends itself to a functional programming approach. Facebook's Pete Hunt (@floydophone) explores how one would go about writing web apps in a functional manner. Spoiler alert:

+ +
+

This is React. It’s not about templates, or data binding, or DOM manipulation. It’s about using functional programming with a virtual DOM representation to build ambitious, high-performance apps with JavaScript.

+ +

Read the full post...

+
+ +

Pete also explains this in detail at his #MeteorDevShop talk (about 30 Minutes):

+ + +

Kioo: Separating markup and logic #

+

Creighton Kirkendall created Kioo, which adds Enlive-style templating to React. HTML templates are separated from the application logic. Kioo comes with separate examples for both Om and Reagent.

+ +

A basic example from github:

+
<!DOCTYPE html>
+<html lang="en">
+  <body>
+    <header>
+      <h1>Header placeholder</h1>
+      <ul id="navigation">
+        <li class="nav-item"><a href="#">Placeholder</a></li>
+      </ul>
+    </header>
+    <div class="content">place holder</div>
+  </body>
+</html>
+
...
+
+(defn my-nav-item [[caption func]]
+  (kioo/component "main.html" [:.nav-item]
+    {[:a] (do-> (content caption)
+                (set-attr :onClick func))}))
+
+(defn my-header [heading nav-elms]
+  (kioo/component "main.html" [:header]
+    {[:h1] (content heading)
+     [:ul] (content (map my-nav-item nav-elms))}))
+
+(defn my-page [data]
+  (kioo/component "main.html"
+    {[:header] (substitute (my-header (:heading data)
+                                      (:navigation data)))
+     [:.content] (content (:content data))}))
+
+(def app-state (atom {:heading    "main"
+                      :content    "Hello World"
+                      :navigation [["home" #(js/alert %)]
+                                   ["next" #(js/alert %)]]}))
+
+(om/root app-state my-page (.-body js/document))
+

Om #

+

In an interview with David Nolen, Tom Coupland (@tcoupland) of InfoQ provides a nice summary of recent developments around Om ("Om: Enhancing Facebook's React with Immutability").

+ +
+

David [Nolen]: I think people are starting to see the limitations of just JavaScript and jQuery and even more structured solutions like Backbone, Angular, Ember, etc. React is a fresh approach to the DOM problem that seems obvious in hindsight.

+ +

Read the full interview...

+
+

A slice of React, ClojureScript and Om #

+

Fredrik Dyrkell (@lexicallyscoped) rewrote part of the React tutorial in both ClojureScript and Om, along with short, helpful explanations.

+ +
+

React has sparked a lot of interest in the Clojure community lately [...]. At the very core, React lets you build up your DOM representation in a functional fashion by composing pure functions and you have a simple building block for everything: React components.

+ +

Read the full post...

+
+ +

In a separate post, Dyrkell breaks down how to build a binary clock component in Om.

+ +

[Demo] [Code]

+

Time Travel: Implementing undo in Om #

+

David Nolen shows how to leverage immutable data structures to add global undo functionality to an app – using just 13 lines of ClojureScript.

+

A Step-by-Step Om Walkthrough #

+

Josh Lehman took the time to create an extensive step-by-step walkthrough of the React tutorial in Om. The well-documented source is on github.

+

Omkara #

+

brendanyounger created omkara, a starting point for ClojureScript web apps based on Om/React. It aims to take advantage of server-side rendering and comes with a few tips on getting started with Om/React projects.

+

Om Experience Report #

+

Adam Solove (@asolove) dives a little deeper into Om, React and ClojureScript. He shares some helpful tips he gathered while building his CartoCrayon prototype.

+

Not-so-random Tweet #

+
+ +
+
+

Community Round-up #14

January 6, 2014 by Vjeux

@@ -364,56 +476,6 @@ componentDidUpdate: function() {
-
-

React v0.8

-

December 19, 2013 by Paul O'Shannessy

-
-
-

I'll start by answering the obvious question:

- -
-

What happened to 0.6 and 0.7?

-
- -

It's become increasingly obvious since our launch in May that people want to use React on the server. With the server-side rendering abilities, that's a perfect fit. However using the same copy of React on the server and then packaging it up for the client is surprisingly a harder problem. People have been using our react-tools module which includes React, but when browserifying that ends up packaging all of esprima and some other dependencies that aren't needed on the client. So we wanted to make this whole experience better.

- -

We talked with Jeff Barczewski who was the owner of the react module on npm. He was kind enough to transition ownership to us and release his package under a different name: autoflow. I encourage you to check it out if you're writing a lot of asynchronous code. In order to not break all of react's current users of 0.7.x, we decided to bump our version to 0.8 and skip the issue entirely. We're also including a warning if you use our react module like you would use the previous package.

- -

In order to make the transition to 0.8 for our current users as painless as possible, we decided to make 0.8 primarily a bug fix release on top of 0.5. No public APIs were changed (even if they were already marked as deprecated). We haven't added any of the new features we have in master, though we did take the opportunity to pull in some improvements to internals.

- -

We hope that by releasing react on npm, we will enable a new set of uses that have been otherwise difficult. All feedback is welcome!

-

Changelog #

React #

-
    -
  • Added support for more attributes: - -
      -
    • rows & cols for <textarea>
    • -
    • defer & async for <script>
    • -
    • loop for <audio> & <video>
    • -
    • autoCorrect for form fields (a non-standard attribute only supported by mobile WebKit)
    • -
  • -
  • Improved error messages
  • -
  • Fixed Selection events in IE11
  • -
  • Added onContextMenu events
  • -
-

React with Addons #

-
    -
  • Fixed bugs with TransitionGroup when children were undefined
  • -
  • Added support for onTransition
  • -
-

react-tools #

-
    -
  • Upgraded jstransform and esprima-fb
  • -
-

JSXTransformer #

-
    -
  • Added support for use in IE8
  • -
  • Upgraded browserify, which reduced file size by ~65KB (16KB gzipped)
  • -
- -
-
- @@ -90,6 +90,56 @@
+
+

React v0.8

+

December 19, 2013 by Paul O'Shannessy

+
+
+

I'll start by answering the obvious question:

+ +
+

What happened to 0.6 and 0.7?

+
+ +

It's become increasingly obvious since our launch in May that people want to use React on the server. With the server-side rendering abilities, that's a perfect fit. However using the same copy of React on the server and then packaging it up for the client is surprisingly a harder problem. People have been using our react-tools module which includes React, but when browserifying that ends up packaging all of esprima and some other dependencies that aren't needed on the client. So we wanted to make this whole experience better.

+ +

We talked with Jeff Barczewski who was the owner of the react module on npm. He was kind enough to transition ownership to us and release his package under a different name: autoflow. I encourage you to check it out if you're writing a lot of asynchronous code. In order to not break all of react's current users of 0.7.x, we decided to bump our version to 0.8 and skip the issue entirely. We're also including a warning if you use our react module like you would use the previous package.

+ +

In order to make the transition to 0.8 for our current users as painless as possible, we decided to make 0.8 primarily a bug fix release on top of 0.5. No public APIs were changed (even if they were already marked as deprecated). We haven't added any of the new features we have in master, though we did take the opportunity to pull in some improvements to internals.

+ +

We hope that by releasing react on npm, we will enable a new set of uses that have been otherwise difficult. All feedback is welcome!

+

Changelog #

React #

+
    +
  • Added support for more attributes: + +
      +
    • rows & cols for <textarea>
    • +
    • defer & async for <script>
    • +
    • loop for <audio> & <video>
    • +
    • autoCorrect for form fields (a non-standard attribute only supported by mobile WebKit)
    • +
  • +
  • Improved error messages
  • +
  • Fixed Selection events in IE11
  • +
  • Added onContextMenu events
  • +
+

React with Addons #

+
    +
  • Fixed bugs with TransitionGroup when children were undefined
  • +
  • Added support for onTransition
  • +
+

react-tools #

+
    +
  • Upgraded jstransform and esprima-fb
  • +
+

JSXTransformer #

+
    +
  • Added support for use in IE8
  • +
  • Upgraded browserify, which reduced file size by ~65KB (16KB gzipped)
  • +
+ +
+
+

React v0.5.2, v0.4.2

December 18, 2013 by Paul O'Shannessy

@@ -452,27 +502,6 @@ Is this some sort of template language? Specifically no. This might have been th
-
-

React v0.5.1

-

October 29, 2013 by Paul O'Shannessy

-
-
-

This release focuses on fixing some small bugs that have been uncovered over the past two weeks. I would like to thank everybody involved, specifically members of the community who fixed half of the issues found. Thanks to Ben Alpert, Andrey Popp, and Laurence Rowe for their contributions!

-

Changelog #

React #

-
    -
  • Fixed bug with <input type="range"> and selection events.
  • -
  • Fixed bug with selection and focus.
  • -
  • Made it possible to unmount components from the document root.
  • -
  • Fixed bug for disabled attribute handling on non-<input> elements.
  • -
-

React with Addons #

-
    -
  • Fixed bug with transition and animation event detection.
  • -
- -
-
- @@ -90,6 +90,27 @@
+
+

React v0.5.1

+

October 29, 2013 by Paul O'Shannessy

+
+
+

This release focuses on fixing some small bugs that have been uncovered over the past two weeks. I would like to thank everybody involved, specifically members of the community who fixed half of the issues found. Thanks to Ben Alpert, Andrey Popp, and Laurence Rowe for their contributions!

+

Changelog #

React #

+
    +
  • Fixed bug with <input type="range"> and selection events.
  • +
  • Fixed bug with selection and focus.
  • +
  • Made it possible to unmount components from the document root.
  • +
  • Fixed bug for disabled attribute handling on non-<input> elements.
  • +
+

React with Addons #

+
    +
  • Fixed bug with transition and animation event detection.
  • +
+ +
+
+

React v0.5

October 16, 2013 by Paul O'Shannessy

@@ -370,48 +391,6 @@
-
-

Use React and JSX in Python Applications

-

August 19, 2013 by Kunal Mehta

-
-
-

Today we're happy to announce the initial release of PyReact, which makes it easier to use React and JSX in your Python applications. It's designed to provide an API to transform your JSX files into JavaScript, as well as provide access to the latest React source files.

-

Usage #

-

Transform your JSX files via the provided jsx module:

-
from react import jsx
-
-# For multiple paths, use the JSXTransformer class.
-transformer = jsx.JSXTransformer()
-for jsx_path, js_path in my_paths:
-    transformer.transform(jsx_path, js_path)
-
-# For a single file, you can use a shortcut method.
-jsx.transform('path/to/input/file.jsx', 'path/to/output/file.js')
-
-

For full paths to React files, use the source module:

-
from react import source
-
-# path_for raises IOError if the file doesn't exist.
-react_js = source.path_for('react.min.js')
-

Django #

-

PyReact includes a JSX compiler for django-pipeline. Add it to your project's pipeline settings like this:

-
PIPELINE_COMPILERS = (
-  'react.utils.pipeline.JSXCompiler',
-)
-

Installation #

-

PyReact is hosted on PyPI, and can be installed with pip:

-
$ pip install PyReact
-
-

Alternatively, add it into your requirements file:

-
PyReact==0.1.1
-
-

Dependencies: PyReact uses PyExecJS to execute the bundled React code, which requires that a JS runtime environment is installed on your machine. We don't explicitly set a dependency on a runtime environment; Mac OS X comes bundled with one. If you're on a different platform, we recommend PyV8.

- -

For the initial release, we've only tested on Python 2.7. Look out for support for Python 3 in the future, and if you see anything that can be improved, we welcome your contributions!

- -
-
- @@ -90,6 +90,48 @@
+
+

Use React and JSX in Python Applications

+

August 19, 2013 by Kunal Mehta

+
+
+

Today we're happy to announce the initial release of PyReact, which makes it easier to use React and JSX in your Python applications. It's designed to provide an API to transform your JSX files into JavaScript, as well as provide access to the latest React source files.

+

Usage #

+

Transform your JSX files via the provided jsx module:

+
from react import jsx
+
+# For multiple paths, use the JSXTransformer class.
+transformer = jsx.JSXTransformer()
+for jsx_path, js_path in my_paths:
+    transformer.transform(jsx_path, js_path)
+
+# For a single file, you can use a shortcut method.
+jsx.transform('path/to/input/file.jsx', 'path/to/output/file.js')
+
+

For full paths to React files, use the source module:

+
from react import source
+
+# path_for raises IOError if the file doesn't exist.
+react_js = source.path_for('react.min.js')
+

Django #

+

PyReact includes a JSX compiler for django-pipeline. Add it to your project's pipeline settings like this:

+
PIPELINE_COMPILERS = (
+  'react.utils.pipeline.JSXCompiler',
+)
+

Installation #

+

PyReact is hosted on PyPI, and can be installed with pip:

+
$ pip install PyReact
+
+

Alternatively, add it into your requirements file:

+
PyReact==0.1.1
+
+

Dependencies: PyReact uses PyExecJS to execute the bundled React code, which requires that a JS runtime environment is installed on your machine. We don't explicitly set a dependency on a runtime environment; Mac OS X comes bundled with one. If you're on a different platform, we recommend PyV8.

+ +

For the initial release, we've only tested on Python 2.7. Look out for support for Python 3 in the future, and if you see anything that can be improved, we welcome your contributions!

+ +
+
+

Community Round-up #6

August 5, 2013 by Vjeux

@@ -322,47 +364,6 @@
-
-

React v0.4.0

-

July 17, 2013 by Paul O'Shannessy

-
-
-

Over the past 2 months we've been taking feedback and working hard to make React even better. We fixed some bugs, made some under-the-hood improvements, and added several features that we think will improve the experience developing with React. Today we're proud to announce the availability of React v0.4!

- -

This release could not have happened without the support of our growing community. Since launch day, the community has contributed blog posts, questions to the Google Group, and issues and pull requests on GitHub. We've had contributions ranging from documentation improvements to major changes to React's rendering. We've seen people integrate React into the tools they're using and the products they're building, and we're all very excited to see what our budding community builds next!

- -

React v0.4 has some big changes. We've also restructured the documentation to better communicate how to use React. We've summarized the changes below and linked to documentation where we think it will be especially useful.

- -

When you're ready, go download it!

-

React #

-
    -
  • Switch from using id attribute to data-reactid to track DOM nodes. This allows you to integrate with other JS and CSS libraries more easily.
  • -
  • Support for more DOM elements and attributes (e.g., <canvas>)
  • -
  • Improved server-side rendering APIs. React.renderComponentToString(<component>, callback) allows you to use React on the server and generate markup which can be sent down to the browser.
  • -
  • prop improvements: validation and default values. Read our blog post for details...
  • -
  • Support for the key prop, which allows for finer control over reconciliation. Read the docs for details...
  • -
  • Removed React.autoBind. Read our blog post for details...
  • -
  • Improvements to forms. We've written wrappers around <input>, <textarea>, <option>, and <select> in order to standardize many inconsistencies in browser implementations. This includes support for defaultValue, and improved implementation of the onChange event, and circuit completion. Read the docs for details...
  • -
  • We've implemented an improved synthetic event system that conforms to the W3C spec.
  • -
  • Updates to your component are batched now, which may result in a significantly faster re-render of components. this.setState now takes an optional callback as its second parameter. If you were using onClick={this.setState.bind(this, state)} previously, you'll want to make sure you add a third parameter so that the event is not treated as the callback.
  • -
-

JSX #

-
    -
  • Support for comment nodes <div>{/* this is a comment and won't be rendered */}</div>
  • -
  • Children are now transformed directly into arguments instead of being wrapped in an array -E.g. <div><Component1/><Component2/></div> is transformed into React.DOM.div(null, Component1(null), Component2(null)). -Previously this would be transformed into React.DOM.div(null, [Component1(null), Component2(null)]). -If you were using React without JSX previously, your code should still work.
  • -
-

react-tools #

-
    -
  • Fixed a number of bugs when transforming directories
  • -
  • No longer re-write require()s to be relative unless specified
  • -
- -
-
- @@ -90,6 +90,47 @@
+
+

React v0.4.0

+

July 17, 2013 by Paul O'Shannessy

+
+
+

Over the past 2 months we've been taking feedback and working hard to make React even better. We fixed some bugs, made some under-the-hood improvements, and added several features that we think will improve the experience developing with React. Today we're proud to announce the availability of React v0.4!

+ +

This release could not have happened without the support of our growing community. Since launch day, the community has contributed blog posts, questions to the Google Group, and issues and pull requests on GitHub. We've had contributions ranging from documentation improvements to major changes to React's rendering. We've seen people integrate React into the tools they're using and the products they're building, and we're all very excited to see what our budding community builds next!

+ +

React v0.4 has some big changes. We've also restructured the documentation to better communicate how to use React. We've summarized the changes below and linked to documentation where we think it will be especially useful.

+ +

When you're ready, go download it!

+

React #

+
    +
  • Switch from using id attribute to data-reactid to track DOM nodes. This allows you to integrate with other JS and CSS libraries more easily.
  • +
  • Support for more DOM elements and attributes (e.g., <canvas>)
  • +
  • Improved server-side rendering APIs. React.renderComponentToString(<component>, callback) allows you to use React on the server and generate markup which can be sent down to the browser.
  • +
  • prop improvements: validation and default values. Read our blog post for details...
  • +
  • Support for the key prop, which allows for finer control over reconciliation. Read the docs for details...
  • +
  • Removed React.autoBind. Read our blog post for details...
  • +
  • Improvements to forms. We've written wrappers around <input>, <textarea>, <option>, and <select> in order to standardize many inconsistencies in browser implementations. This includes support for defaultValue, and improved implementation of the onChange event, and circuit completion. Read the docs for details...
  • +
  • We've implemented an improved synthetic event system that conforms to the W3C spec.
  • +
  • Updates to your component are batched now, which may result in a significantly faster re-render of components. this.setState now takes an optional callback as its second parameter. If you were using onClick={this.setState.bind(this, state)} previously, you'll want to make sure you add a third parameter so that the event is not treated as the callback.
  • +
+

JSX #

+
    +
  • Support for comment nodes <div>{/* this is a comment and won't be rendered */}</div>
  • +
  • Children are now transformed directly into arguments instead of being wrapped in an array +E.g. <div><Component1/><Component2/></div> is transformed into React.DOM.div(null, Component1(null), Component2(null)). +Previously this would be transformed into React.DOM.div(null, [Component1(null), Component2(null)]). +If you were using React without JSX previously, your code should still work.
  • +
+

react-tools #

+
    +
  • Fixed a number of bugs when transforming directories
  • +
  • No longer re-write require()s to be relative unless specified
  • +
+ +
+
+

New in React v0.4: Prop Validation and Default Values

July 11, 2013 by Paul O'Shannessy

@@ -333,30 +374,6 @@
-
-

React v0.3.3

-

June 21, 2013 by Paul O'Shannessy

-
-
-

We have a ton of great stuff coming in v0.4, but in the meantime we're releasing v0.3.3. This release addresses some small issues people were having and simplifies our tools to make them easier to use.

-

react-tools #

-
    -
  • Upgrade Commoner so require statements are no longer relativized when passing through the transformer. This was a feature needed when building React, but doesn't translate well for other consumers of bin/jsx.
  • -
  • Upgraded our dependencies on Commoner and Recast so they use a different directory for their cache.
  • -
  • Freeze our esprima dependency.
  • -
-

React #

-
    -
  • Allow reusing the same DOM node to render different components. e.g. React.renderComponent(<div/>, domNode); React.renderComponent(<span/>, domNode); will work now.
  • -
-

JSXTransformer #

-
    -
  • Improved the in-browser transformer so that transformed scripts will execute in the expected scope. The allows components to be defined and used from separate files.
  • -
- -
-
- @@ -90,6 +90,30 @@
+
+

React v0.3.3

+

June 21, 2013 by Paul O'Shannessy

+
+
+

We have a ton of great stuff coming in v0.4, but in the meantime we're releasing v0.3.3. This release addresses some small issues people were having and simplifies our tools to make them easier to use.

+

react-tools #

+
    +
  • Upgrade Commoner so require statements are no longer relativized when passing through the transformer. This was a feature needed when building React, but doesn't translate well for other consumers of bin/jsx.
  • +
  • Upgraded our dependencies on Commoner and Recast so they use a different directory for their cache.
  • +
  • Freeze our esprima dependency.
  • +
+

React #

+
    +
  • Allow reusing the same DOM node to render different components. e.g. React.renderComponent(<div/>, domNode); React.renderComponent(<span/>, domNode); will work now.
  • +
+

JSXTransformer #

+
    +
  • Improved the in-browser transformer so that transformed scripts will execute in the expected scope. The allows components to be defined and used from separate files.
  • +
+ +
+
+

Community Round-up #2

June 19, 2013 by Vjeux

diff --git a/docs/addons.html b/docs/addons.html index 4bfc1b00db..96bef8c0f7 100644 --- a/docs/addons.html +++ b/docs/addons.html @@ -316,6 +316,27 @@
+ + diff --git a/docs/animation.html b/docs/animation.html index 4ac054068d..6f2d88c812 100644 --- a/docs/animation.html +++ b/docs/animation.html @@ -316,6 +316,27 @@
+ + diff --git a/docs/class-name-manipulation.html b/docs/class-name-manipulation.html index 4a37ac5c6c..ce40b6fe41 100644 --- a/docs/class-name-manipulation.html +++ b/docs/class-name-manipulation.html @@ -316,6 +316,27 @@
+ + diff --git a/docs/clone-with-props.html b/docs/clone-with-props.html index 689f27e05f..c5a0b49793 100644 --- a/docs/clone-with-props.html +++ b/docs/clone-with-props.html @@ -316,6 +316,27 @@
+ + diff --git a/docs/complementary-tools.html b/docs/complementary-tools.html index c954549a89..8468195068 100644 --- a/docs/complementary-tools.html +++ b/docs/complementary-tools.html @@ -316,6 +316,27 @@ + + diff --git a/docs/component-api.html b/docs/component-api.html index 7b3331c6f0..0d65d8678d 100644 --- a/docs/component-api.html +++ b/docs/component-api.html @@ -316,6 +316,27 @@ + + diff --git a/docs/component-specs.html b/docs/component-specs.html index 41240a9093..7e65520ebe 100644 --- a/docs/component-specs.html +++ b/docs/component-specs.html @@ -316,6 +316,27 @@ + + diff --git a/docs/displaying-data.html b/docs/displaying-data.html index d7a018563f..ace7e4be0c 100644 --- a/docs/displaying-data.html +++ b/docs/displaying-data.html @@ -316,6 +316,27 @@ + + diff --git a/docs/dom-differences.html b/docs/dom-differences.html index fb4d4c1e29..276f32a7fa 100644 --- a/docs/dom-differences.html +++ b/docs/dom-differences.html @@ -316,6 +316,27 @@ + + diff --git a/docs/events.html b/docs/events.html index f92f6dac2a..24a93f4582 100644 --- a/docs/events.html +++ b/docs/events.html @@ -316,6 +316,27 @@ + + diff --git a/docs/examples.html b/docs/examples.html index 81ad418035..d0aac1597b 100644 --- a/docs/examples.html +++ b/docs/examples.html @@ -316,6 +316,27 @@ + + diff --git a/docs/flux-overview.html b/docs/flux-overview.html new file mode 100644 index 0000000000..c0388875d3 --- /dev/null +++ b/docs/flux-overview.html @@ -0,0 +1,526 @@ + + + + + + + React | Flux Application Architecture + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Flux Application Architecture

+
+

Flux is the application architecture that Facebook uses for building client-side web applications. It complements React's composable view components by utilizing a unidirectional data flow. It's more of a pattern rather than a formal framework, and you can start using Flux immediately without a lot of new code.

+ +
+ +

Flux applications have three major parts: the dispatcher, the stores, and the views (React components). These should not be confused with Model-View-Controller. Controllers do exist in a Flux application, but they are controller-views — views often found at the top of the hierarchy that retrieve data from the stores and pass this data down to their children. Additionally, actions — dispatcher helper methods — are often used to support a semantic dispatcher API. It can be useful to think of them as a fourth part of the Flux update cycle.

+ +

Flux eschews MVC in favor of a unidirectional data flow. When a user interacts with a React view, the view propagates an action through a central dispatcher, to the various stores that hold the application's data and business logic, which updates all of the views that are affected. This works especially well with React's declarative programming style, which allows the store to send updates without specifying how to transition views between states.

+ +

We originally set out to deal correctly with derived data: for example, we wanted to show an unread count for message threads while another view showed a list of threads, with the unread ones highlighted. This was difficult to handle with MVC — marking a single thread as read would update the thread model, and then also need to update the unread count model. These dependencies and cascading updates often occur in a large MVC application, leading to a tangled weave of data flow and unpredictable results.

+ +

Control is inverted with stores: the stores accept updates and reconcile them as appropriate, rather than depending on something external to update its data in a consistent way. Nothing outside the store has any insight into how it manages the data for its domain, helping to keep a clear separation of concerns. This also makes stores more testable than models, especially since stores have no direct setter methods like setAsRead(), but instead have only an input point for the payload, which is delivered through the dispatcher and originates with actions.

+

Structure and Data Flow #

+

Data in a Flux application flows in a single direction, in a cycle:

+ +
+Views ---> (actions) ----> Dispatcher ---> (registered callback) ---> Stores -------+
+Ʌ                                                                                   |
+|                                                                                   V
++-- (Controller-Views "change" event handlers) ---- (Stores emit "change" events) --+
+
+ +

A unidirectional data flow is central to the Flux pattern, and in fact Flux takes its name from the Latin word for flow. In the above diagram, the dispatcher, stores and views are independent nodes with distinct inputs and outputs. The actions are simply discrete, semantic helper functions that facilitate passing data to the dispatcher.

+ +

All data flows through the dispatcher as a central hub. Actions most often originate from user interactions with the views, and are nothing more than a call into the dispatcher. The dispatcher then invokes the callbacks that the stores have registered with it, effectively dispatching the data payload contained in the actions to all stores. Within their registered callbacks, stores determine which actions they are interested in, and respond accordingly. The stores then emit a "change" event to alert the controller-views that a change to the data layer has occurred. Controller-views listen for these events and retrieve data from the stores in an event handler. The controller-views call their own render() method via setState() or forceUpdate(), updating themselves and all of their children.

+ +

This structure allows us to reason easily about our application in a way that is reminiscent of functional reactive programming, or more specifically data-flow programming or flow-based programming, where data flows through the application in a single direction — there are no two-way bindings. Application state is maintained only in the stores, allowing the different parts of the application to remain highly decoupled. Where dependencies do occur between stores, they are kept in a strict hierarchy, with synchronous updates managed by the dispatcher.

+ +

We found that two-way data bindings led to cascading updates, where changing one object led to another object changing, which could also trigger more updates. As applications grew, these cascading updates made it very difficult to predict what would change as the result of one user interaction. When updates can only change data within a single round, the system as a whole becomes more predictable.

+ +

Let's look at the various parts of the Flux update cycle up close. A good place to start is the dispatcher.

+

A Single Dispatcher #

+

The dispatcher is the central hub that manages all data flow in a Flux application. It is essentially a registry of callbacks into the stores. Each store registers itself and provides a callback. When the dispatcher responds to an action, all stores in the application are sent the data payload provided by the action via the callbacks in the registry.

+ +

As an application grows, the dispatcher becomes more vital, as it can manage dependencies between stores by invoking the registered callbacks in a specific order. Stores can declaratively wait for other stores to finish updating, and then update themselves accordingly.

+

Stores #

+

Stores contain the application state and logic. Their role is somewhat similar to a model in a traditional MVC, but they manage the state of many objects — they are not instances of one object. Nor are they the same as Backbone's collections. More than simply managing a collection of ORM-style objects, stores manage the application state for a particular domain within the application.

+ +

For example, Facebook's Lookback Video Editor utilized a TimeStore that kept track of the playback time position and the playback state. On the other hand, the same application's ImageStore kept track of a collection of images. The TodoStore in our TodoMVC example is similar in that it manages a collection of to-do items. A store exhibits characteristics of both a collection of models and a singleton model of a logical domain.

+ +

As mentioned above, a store registers itself with the dispatcher and provides it with a callback. This callback receives the action's data payload as a parameter. The payload contains a type attribute, identifying the action's type. Within the store's registered callback, a switch statement based on the action's type is used to interpret the payload and to provide the proper hooks into the store's internal methods. This allows an action to result in an update to the state of the store, via the dispatcher. After the stores are updated, they broadcast an event declaring that their state has changed, so the views may query the new state and update themselves.

+

Views and Controller-Views #

+

React provides the kind of composable views we need for the view layer. Close to the top of the nested view hierarchy, a special kind of view listens for events that are broadcast by the stores that it depends on. One could call this a controller-view, as it provides the glue code to get the data from the stores and to pass this data down the chain of its descendants. We might have one of these controller-views governing any significant section of the page.

+ +

When it receives the event from the store, it first requests the new data it needs via the stores' public getter methods. It then calls its own setState() or forceUpdate() methods, causing its render() method and the render() method of all its descendants to run.

+ +

We often pass the entire state of the store down the chain of views in a single object, allowing different descendants to use what they need. In addition to keeping the controller-like behavior at the top of the hierarchy, and thus keeping our descendant views as functionally pure as possible, passing down the entire state of the store in a single object also has the effect of reducing the number of props we need to manage.

+ +

Occasionally we may need to add additional controller-views deeper in the hierarchy to keep components simple. This might help us to better encapsulate a section of the hierarchy related to a specific data domain. Be aware, however, that controller-views deeper in the hierarchy can violate the singular flow of data by introducing a new, potentially conflicting entry point for the data flow. In making the decision of whether to add a deep controller-view, balance the gain of simpler components against the complexity of multiple data updates flowing into the hierarchy at different points. These multiple data updates can lead to odd effects, with React's render method getting invoked repeatedly by updates from different controller-views, potentially increasing the difficulty of debugging.

+

Actions #

+

The dispatcher exposes a method that allows a view to trigger a dispatch to the stores, and to include a payload of data, or an action. The action construction may be wrapped into a semantic helper method which sends the payload to the dispatcher. For example, we may want to change the text of a to-do item in a to-do list application. We would create an action with a function signature like updateText(todoId, newText) in our TodoActions module. This method may be invoked from within our views' event handlers, so we can call it in response to a user action. This action method also adds the action type to the payload, so that when the payload is interpreted in the store, it can respond appropriately to a payload with a particular action type. In our example, this type might be named something like TODO_UPDATE_TEXT.

+ +

Actions may also come from other places, such as the server. This happens, for example, during data initialization. It may also happen when the server returns an error code or when the server has updates to provide to the application. We'll talk more about server actions in a future article. In this post we're only concerned with the basics of the data flow.

+

What About that Dispatcher? #

+

As mentioned earlier, the dispatcher is also able to manage dependencies between stores. This functionality is available through the waitFor() method within the Dispatcher class. We did not need to use this method within the extremely simple TodoMVC application, but we have included it in the example dispatcher as an example of what a dispatcher should be able to do in a larger, more complex application.

+ +

Within the TodoStore's registered callback we could explicitly wait for any dependencies to first update before moving forward:

+
case 'TODO_CREATE': 
+  Dispatcher.waitFor([ 
+    PrependedTextStore.dispatcherIndex, 
+    YetAnotherStore.dispatcherIndex 
+  ], function() { 
+    TodoStore.create(PrependedTextStore.getText() + ' ' + action.text); 
+    TodoStore.emit('change'); 
+  }); 
+  break; 
+
+

The arguments for waitFor() are an array of dipatcher registry indexes, and a final callback to invoke after the callbacks at the given indexes have completed. Thus the store that is invoking waitFor() can depend on the state of another store to inform how it should update its own state.

+ +

A problem arises if we create circular dependencies. If Store A waits for Store B, and B waits for A, then we'll have a very bad situation on our hands. We'll need a more robust dispatcher that flags these circular dependencies with console errors, and this is not easily accomplished with promises. Unfortunately, that's a bit beyond the scope of this documentation. In the future we hope to cover how to build a more robust dispatcher and how to initialize, update, and save the state of the application with persistent data, like a web service API.

+ + +
+ + + Next → + +
+
+
+ + + +
+
+ + + + diff --git a/docs/flux-todo-list.html b/docs/flux-todo-list.html new file mode 100644 index 0000000000..8402ffc478 --- /dev/null +++ b/docs/flux-todo-list.html @@ -0,0 +1,985 @@ + + + + + + + React | Flux TodoMVC Tutorial + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + + +
+

Flux TodoMVC Tutorial

+
+

To demonstrate the Flux architecture with some example code, let's take on the classic TodoMVC application. The entire application is available in the React GitHub repo within the todomvc-flux) example directory, but let's walk through the development of it a step at a time.

+ +

To begin, we'll need some boilerplate and get up and running with a module system. Node's module system, based on CommonJS, will fit the bill very nicely and we can build off of react-boilerplate to get up and running quickly. Assuming you have npm installed, simply clone the react-boilerplate code from GitHub, and navigate into the resulting directory in Terminal (or whatever CLI application you like). Next run the npm scripts to get up and running: npm install, then npm run build, and lastly npm start to continuously build using Browserify.

+ +

The TodoMVC example has all this built into it as well, but if you're starting with react-boilerplate make sure you edit your package.json file to match the file structure and dependencies described in the TodoMVC example's package.json, or else your code won't match up with the explanations below.

+

Source Code Structure #

+

The resulting index.js file may be used as the entry point into our app, but we'll put most of our code in a 'js' directory. Let's let Browserify do its thing, and now we'll open a new tab in Terminal (or a GUI file browser) to look at the directory. It should look something like this:

+
myapp 
+  | 
+  + ... 
+  + js
+    |
+    + app.js
+    + bundle.js // generated by Browserify whenever we make changes. 
+  + index.html 
+  + ... 
+
+

Next we'll dive into the js directory, and layout our application's primary directory structure:

+
myapp 
+  | 
+  + ... 
+  + js 
+    | 
+    + actions 
+    + components // all React components, both views and controller-views
+    + constants
+    + dispatcher 
+    + stores 
+    + app.js
+    + bundle.js
+  + index.html
+  + ...
+

Creating a Dispatcher #

+

Now we are ready to create a dispatcher. Here is an naive example of a Dispatcher class, written with JavaScript promises, polyfilled with Jake Archibald's ES6-Promises module.

+
var Promise = require('es6-promise').Promise;
+var merge = require('react/lib/merge');
+
+var _callbacks = [];
+var _promises = [];
+
+/**
+ * Add a promise to the queue of callback invocation promises.
+ * @param {function} callback The Store's registered callback.
+ * @param {object} payload The data from the Action.
+ */
+var _addPromise = function(callback, payload) {
+  _promises.push(new Promise(function(resolve, reject) {
+    if (callback(payload)) {
+      resolve(payload);
+    } else {
+      reject(new Error('Dispatcher callback unsuccessful'));
+    }
+  }));
+};
+
+/**
+ * Empty the queue of callback invocation promises.
+ */
+var _clearPromises = function() {
+  _promises = [];
+};
+
+var Dispatcher = function() {};
+Dispatcher.prototype = merge(Dispatcher.prototype, {
+
+  /**
+   * Register a Store's callback so that it may be invoked by an action.
+   * @param {function} callback The callback to be registered.
+   * @return {number} The index of the callback within the _callbacks array.
+   */
+  register: function(callback) {
+    _callbacks.push(callback);
+    return _callbacks.length - 1; // index
+  },
+
+  /**
+   * dispatch
+   * @param  {object} payload The data from the action.
+   */
+  dispatch: function(payload) {
+    _callbacks.forEach(function(callback) {
+      _addPromise(callback, payload);
+    });
+    Promise.all(_promises).then(_clearPromises);
+  }
+
+}); 
+
+module.exports = Dispatcher; 
+
+

The public API of this basic Dispatcher consists of only two methods: register() and dispatch(). We'll use register() within our stores to register each store's callback. We'll use dispatch() within our actions to trigger the invocation of the callbacks.

+ +

Now we are all set to create a dispatcher that is more specific to our app, which we'll call AppDispatcher.

+
var Dispatcher = require('./Dispatcher');
+
+var merge = require('react/lib/merge');
+
+var AppDispatcher = merge(Dispatcher.prototype, {
+
+  /**
+   * A bridge function between the views and the dispatcher, marking the action
+   * as a view action.  Another variant here could be handleServerAction.
+   * @param  {object} action The data coming from the view.
+   */
+  handleViewAction: function(action) {
+    this.dispatch({
+      source: 'VIEW_ACTION',
+      action: action
+    });
+  }
+
+});
+
+module.exports = AppDispatcher;
+
+

Now we've created an implementation that is a bit more specific to our needs, with a helper function we can use in the actions coming from our views' event handlers. We might expand on this later to provide a separate helper for server updates, but for now this is all we need.

+

Creating Stores #

+

We can use Node's EventEmitter to get started with a store. We need EventEmitter to broadcast the 'change' event to our controller-views. So let's take a look at what that looks like. I've omitted some of the code for the sake of brevity, but for the full version see TodoStore.js in the TodoMVC example code.

+
var AppDispatcher = require('../dispatcher/AppDispatcher'); 
+var EventEmitter = require('events').EventEmitter; 
+var TodoConstants = require('../constants/TodoConstants'); 
+var merge = require('react/lib/merge'); 
+
+var CHANGE_EVENT = 'change'; 
+
+var _todos = {}; // collection of todo items 
+
+/**
+ * Create a TODO item. 
+ * @param {string} text The content of the TODO 
+ */ 
+function create(text) { 
+  // Using the current timestamp in place of a real id. 
+  var id = Date.now(); 
+  _todos[id] = { 
+    id: id, 
+    complete: false, 
+    text: text 
+  }; 
+} 
+
+/** 
+ * Delete a TODO item. 
+ * @param {string} id 
+ */ 
+function destroy(id) { 
+  delete _todos[id]; 
+} 
+
+var TodoStore = merge(EventEmitter.prototype, { 
+
+  /** 
+   * Get the entire collection of TODOs. 
+   * @return {object} 
+   */ 
+  getAll: function() { 
+    return _todos; 
+  }, 
+
+  emitChange: function() { 
+    this.emit(CHANGE_EVENT); 
+  }, 
+
+  /** 
+   * @param {function} callback 
+   */ 
+  addChangeListener: function(callback) { 
+    this.on(CHANGE_EVENT, callback); 
+  }, 
+
+  /** 
+   * @param {function} callback 
+   */ 
+  removeChangeListener: function(callback) { 
+    this.removeListener(CHANGE_EVENT, callback); 
+  } 
+
+  dispatcherIndex: AppDispatcher.register(function(payload) { 
+    var action = payload.action; 
+    var text; 
+
+    switch(action.actionType) { 
+      case TodoConstants.TODO_CREATE: 
+        text = action.text.trim(); 
+        if (text !== '') { 
+          create(text); 
+          TodoStore.emitChange(); 
+        } 
+        break; 
+
+      case TodoConstants.TODO_DESTROY: 
+        destroy(action.id); 
+        break; 
+
+    // add more cases for other actionTypes, like TODO_UPDATE, etc. 
+    }
+
+    return true; // No errors. Needed by promise in Dispatcher. 
+  }) 
+
+}); 
+
+module.exports = TodoStore; 
+
+

There are a few important things to note in the above code. To start, we are maintaining a private data structure called _todos. This object contains all the individual to-do items. Because this variable lives outside the class, but within the closure of the module, it remains private — it cannot be directly changed from the outside. This helps us preserve a distinct input/output interface for the flow of data by making it impossible to update the store without using an action.

+ +

Another important part is the registration of the store's callback with the dispatcher. We pass in our payload handling callback to the dispatcher and preserve the index that this store has in the dispatcher's registry. The callback function currently only handles one actionType, but later we can add as many as we need.

+

Listening to Changes with a Controller-View #

+

We need a React component near the top of our component hierarchy to listen for changes in the store. In a larger app, we would have more of these listening components, perhaps one for every section of the page. In Facebook's Ads Creation Tool, we have many of these controller-like views, each governing a specific section of the UI. In the Lookback Video Editor, we only had two: one for the animated preview and one for the image selection interface. Here's one for our TodoMVC example. Again, this is slightly abbreviated, but for the full code you can take a look at the TodoMVC example's TodoApp.react.js

+
/** @jsx React.DOM */ 
+
+var Footer = require('./Footer.react'); 
+var Header = require('./Header.react'); 
+var MainSection = require('./MainSection.react'); 
+var React = require('react'); 
+var TodoStore = require('../stores/TodoStore'); 
+
+function getTodoState() { 
+  return { 
+    allTodos: TodoStore.getAll() 
+  }; 
+} 
+
+var TodoApp = React.createClass({ 
+
+  getInitialState: function() { 
+    return getTodoState(); 
+  }, 
+
+  componentDidMount: function() { 
+    TodoStore.addChangeListener(this._onChange); 
+  }, 
+
+  componentWillUnmount: function() { 
+    TodoStore.removeChangeListener(this._onChange); 
+  }, 
+
+  /**
+   * @return {object}
+   */
+  render: function() {
+    return (
+      <div>
+        <Header />
+        <MainSection
+          allTodos={this.state.allTodos}
+          areAllComplete={this.state.areAllComplete}
+        />
+        <Footer allTodos={this.state.allTodos} />
+      </div>
+    );
+  }, 
+
+  _onChange: function() { 
+    this.setState(getTodoState()); 
+  } 
+
+}); 
+
+module.exports = TodoApp; 
+
+

Now we're in our familiar React territory, utilizing React's lifecycle methods. We set up the initial state of this controller-view in getInitialState(), register an event listener in componentDidMount(), and then clean up after ourselves within componentWillUnmount(). We render a containing div and pass down the collection of states we got from the TodoStore.

+ +

The Header component contains the primary text input for the application, but it does not need to know the state of the store. The MainSection and Footer do need this data, so we pass it down to them.

+

More Views #

+

At a high level, the React component hierarchy of the app looks like this:

+
<TodoApp> 
+  <Header> 
+    <TodoTextInput /> 
+
+    <MainSection> 
+      <ul> 
+        <TodoItem /> 
+      </ul> 
+    </MainSection> 
+
+</TodoApp> 
+
+

If a TodoItem is in edit mode, it will also render a TodoTextInput as a child. Let's take a look at how some of these components display the data they receive as props, and how they communicate through actions with the dispatcher. +The MainSection needs to iterate over the collection of to-do items it received from TodoApp to create the list of TodoItems. In the component's render() method, we can do that iteration like so:

+
var allTodos = this.props.allTodos; 
+
+for (var key in allTodos) { 
+  todos.push(<TodoItem key={key} todo={allTodos[key]} />); 
+} 
+
+return ( 
+  <section id="main"> 
+  <ul id="todo-list">{todos}</ul> 
+); 
+
+

Now each TodoItem can display it's own text, and perform actions utilizing it's own ID. Explaining all the different actions that a TodoItem can invoke in the TodoMVC example goes beyond the scope of this article, but let's just take a look at the action that deletes one of the to-do items. Here is an abbreviated version of the TodoItem:

+
/** @jsx React.DOM */ 
+
+var React = require('react'); 
+var TodoActions = require('../actions/TodoActions'); 
+var TodoTextInput = require('./TodoTextInput.react'); 
+
+var TodoItem = React.createClass({ 
+
+  propTypes: { 
+    todo: React.PropTypes.object.isRequired 
+  }, 
+
+  render: function() { 
+    var todo = this.props.todo; 
+
+    return ( 
+      <li 
+        key={todo.id}> 
+        <label> 
+          {todo.text} 
+        </label> 
+        <button className="destroy" onClick={this._onDestroyClick} /> 
+      </li> 
+    ); 
+  }, 
+
+  _onDestroyClick: function() { 
+    TodoActions.destroy(this.props.todo.id); 
+  } 
+
+}); 
+
+module.exports = TodoItem; 
+
+

With a destroy action available in our library of TodoActions, and a store ready to handle it, connecting the user's interaction with application state changes could not be simpler. We just wrap our onClick handler around the destroy action, provide it with the id, and we're done. Now the user can click the destroy button and kick off the Flux cycle to update the rest of the application.

+ +

Text input, on the other hand, is just a bit more complicated because we need to hang on to the state of the text input within the React component itself. Let's take a look at how TodoTextInput works.

+ +

As you'll see below, with every change to the input, React expects us to update the state of the component. So when we are finally ready to save the text inside the input, we will put the value held in the component's state in the action's payload. This is UI state, rather than application state, and keeping that distinction in mind is a good guide for where state should live. All application state should live in the store, while components occasionally hold on to UI state. Ideally, React components preserve as little state as possible.

+ +

Because TodoTextInput is being used in multiple places within our application, with different behaviors, we'll need to pass the onSave method in as a prop from the component's parent. This allows onSave to invoke different actions depending on where it is used.

+
/** @jsx React.DOM */ 
+
+var React = require('react'); 
+var ReactPropTypes = React.PropTypes; 
+
+var ENTER_KEY_CODE = 13; 
+
+var TodoTextInput = React.createClass({ 
+
+  propTypes: { 
+    className: ReactPropTypes.string, 
+    id: ReactPropTypes.string, 
+    placeholder: ReactPropTypes.string, 
+    onSave: ReactPropTypes.func.isRequired, 
+    value: ReactPropTypes.string 
+  }, 
+
+  getInitialState: function() { 
+    return { 
+      value: this.props.value || '' 
+    }; 
+  },
+
+  /** 
+   * @return {object} 
+   */ 
+  render: function() /*object*/ { 
+    return ( 
+      <input 
+        className={this.props.className} 
+        id={this.props.id} 
+        placeholder={this.props.placeholder} 
+        onBlur={this._save} 
+        onChange={this._onChange} 
+        onKeyDown={this._onKeyDown} 
+        value={this.state.value} 
+        autoFocus={true} 
+      /> 
+    ); 
+  }, 
+
+  /** 
+   * Invokes the callback passed in as onSave, allowing this component to be 
+   * used in different ways. 
+   */ 
+  _save: function() { 
+    this.props.onSave(this.state.value); 
+    this.setState({ 
+      value: '' 
+    }); 
+  }, 
+
+  /** 
+   * @param {object} event 
+   */ 
+  _onChange: function(/*object*/ event) { 
+    this.setState({ 
+      value: event.target.value 
+    }); 
+  }, 
+
+  /** 
+   * @param {object} event 
+   */ 
+
+  _onKeyDown: function(event) { 
+    if (event.keyCode === ENTER_KEY_CODE) { 
+      this._save(); 
+    } 
+  } 
+
+}); 
+
+module.exports = TodoTextInput; 
+
+

The Header passes in the onSave method as a prop to allow the TodoTextInput to create new +to-do items:

+
/** @jsx React.DOM */ 
+
+var React = require('react'); 
+var TodoActions = require('../actions/TodoActions'); 
+var TodoTextInput = require('./TodoTextInput.react'); 
+
+var Header = React.createClass({ 
+
+  /**
+   * @return {object}
+   */
+  render: function() {
+    return (
+      <header id="header">
+        <h1>todos</h1>
+        <TodoTextInput
+          id="new-todo"
+          placeholder="What needs to be done?"
+          onSave={this._onSave}
+        />
+      </header>
+    );
+  }, 
+
+  /**
+   * Event handler called within TodoTextInput.
+   * Defining this here allows TodoTextInput to be used in multiple places
+   * in different ways.
+   * @param {string} text
+   */
+  _onSave: function(text) {
+    TodoActions.create(text);
+  } 
+
+}); 
+
+module.exports = Header; 
+
+

In a different context, such as in editing mode for an existing to-do item, we might pass an onSave callback that invokes TodoActions.update(text) instead.

+

Creating Semantic Actions #

+

Here is the basic code for the two actions we used above in our views:

+
/** 
+ * TodoActions 
+ */ 
+
+var AppDispatcher = require('../dispatcher/AppDispatcher');
+var TodoConstants = require('../constants/TodoConstants');
+
+var TodoActions = {
+
+  /**
+   * @param  {string} text
+   */
+  create: function(text) {
+    AppDispatcher.handleViewAction({
+      actionType: TodoConstants.TODO_CREATE,
+      text: text
+    });
+  }, 
+
+  /**
+   * @param  {string} id
+   */
+  destroy: function(id) {
+    AppDispatcher.handleViewAction({
+      actionType: TodoConstants.TODO_DESTROY,
+      id: id
+    });
+  }, 
+
+}; 
+
+module.exports = TodoActions; 
+
+

As you can see, we really would not need to have the helpers AppDispatcher.handleViewAction() or TodoActions.create(). We could, in theory, call AppDispatcher.dispatch() directly and provide a payload. But as our application grows, having these helpers keeps the code clean and semantic. It's just a lot cleaner to write TodoActions.destroy(id) instead of writing a whole lot of things that our TodoItem shouldn't have to know about.

+ +

The payload produced by the TodoActions.create() will look like:

+
{ 
+  source: 'VIEW_ACTION', 
+  action: { 
+    type: 'TODO_CREATE', 
+    text: 'Write blog post about Flux' 
+  } 
+} 
+
+

This payload is provided to the TodoStore through its registered callback. The TodoStore then broadcasts the 'change' event, and the MainSection responds by fetching the new collection of to-do items from the TodoStore and changing its state. This change in state causes the TodoApp component to call its own render() method, and the render() method of all of its descendents.

+

Start Me Up #

+

The bootstrap file of our application is app.js. It simply takes the TodoApp component and renders it in the root element of the application.

+
/** @jsx React.DOM */ 
+
+var React = require('react'); 
+
+var TodoApp = require('./components/TodoApp.react'); 
+
+React.renderComponent( 
+  <TodoApp />, 
+  document.getElementById('todoapp') 
+); 
+

Adding Dependency Management to the Dispatcher #

+

As I said previously, our Dispatcher implementation is a bit naive. It's pretty good, but it will not suffice for most applications. We need a way to be able to manage dependencies between Stores. Let's add that functionality with a waitFor() method within the main body of the Dispatcher class.

+ +

We'll need another public method, waitFor().

+
  /**
+   * @param  {array} promisesIndexes
+   * @param  {function} callback
+   */
+  waitFor: function(promiseIndexes, callback) {
+    var selectedPromises = _promises.filter(function(/*object*/ _, /*number*/ j) {
+      return promiseIndexes.indexOf(j) !== -1;
+    });
+    Promise.all(selectedPromises).then(callback);
+  }
+
+

Now within the TodoStore callback we can explicitly wait for any dependencies to first update before moving forward. However, if Store A waits for Store B, and B waits for A, then a circular dependency will occur. A more robust dispatcher is required to flag this scenario with warnings in the console.

+

The Future of Flux #

+

A lot of people ask if Facebook will release Flux as an open source framework. Really, Flux is just an architecture, not a framework. But perhaps a Flux boilerplate project might make sense, if there is enough interest. Please let us know if you'd like to see us do this.

+ +

Thanks for taking the time to read about how we build client-side applications at Facebook. We hope Flux proves as useful to you as it has to us.

+ + +
+ + ← Prev + + +
+
+
+ + + +
+
+ + + + diff --git a/docs/forms.html b/docs/forms.html index 131b67f11b..115606c295 100644 --- a/docs/forms.html +++ b/docs/forms.html @@ -316,6 +316,27 @@ + + diff --git a/docs/getting-started.html b/docs/getting-started.html index 50cf9f2569..f844bf602c 100644 --- a/docs/getting-started.html +++ b/docs/getting-started.html @@ -316,6 +316,27 @@ + + diff --git a/docs/interactivity-and-dynamic-uis.html b/docs/interactivity-and-dynamic-uis.html index 021850ae73..d28f84ca14 100644 --- a/docs/interactivity-and-dynamic-uis.html +++ b/docs/interactivity-and-dynamic-uis.html @@ -316,6 +316,27 @@ + + diff --git a/docs/jsx-gotchas.html b/docs/jsx-gotchas.html index 5f624f3c9f..4869d472a9 100644 --- a/docs/jsx-gotchas.html +++ b/docs/jsx-gotchas.html @@ -316,6 +316,27 @@ + + diff --git a/docs/jsx-in-depth.html b/docs/jsx-in-depth.html index 9c5c0c2dab..6f593261a0 100644 --- a/docs/jsx-in-depth.html +++ b/docs/jsx-in-depth.html @@ -316,6 +316,27 @@ + + diff --git a/docs/more-about-refs.html b/docs/more-about-refs.html index fb20bc0f0a..ee7bf7ae35 100644 --- a/docs/more-about-refs.html +++ b/docs/more-about-refs.html @@ -316,6 +316,27 @@ + + diff --git a/docs/multiple-components.html b/docs/multiple-components.html index 13ff2538a8..94036f6d4a 100644 --- a/docs/multiple-components.html +++ b/docs/multiple-components.html @@ -316,6 +316,27 @@ + + diff --git a/docs/reconciliation.html b/docs/reconciliation.html index 17b391f7d3..97f372a494 100644 --- a/docs/reconciliation.html +++ b/docs/reconciliation.html @@ -316,6 +316,27 @@ + + diff --git a/docs/reusable-components.html b/docs/reusable-components.html index 25b46a36a0..90e546e14f 100644 --- a/docs/reusable-components.html +++ b/docs/reusable-components.html @@ -316,6 +316,27 @@ + + diff --git a/docs/special-non-dom-attributes.html b/docs/special-non-dom-attributes.html index a6ff00108e..d4b34ef775 100644 --- a/docs/special-non-dom-attributes.html +++ b/docs/special-non-dom-attributes.html @@ -316,6 +316,27 @@ + + diff --git a/docs/tags-and-attributes.html b/docs/tags-and-attributes.html index 9dc8d8bbab..5bcd879a3b 100644 --- a/docs/tags-and-attributes.html +++ b/docs/tags-and-attributes.html @@ -316,6 +316,27 @@ + + diff --git a/docs/test-utils.html b/docs/test-utils.html index 7682ff8be5..449d31f6e2 100644 --- a/docs/test-utils.html +++ b/docs/test-utils.html @@ -316,6 +316,27 @@ + + diff --git a/docs/thinking-in-react.html b/docs/thinking-in-react.html index c306efd7b5..498b1d41df 100644 --- a/docs/thinking-in-react.html +++ b/docs/thinking-in-react.html @@ -316,6 +316,27 @@ + + diff --git a/docs/tooling-integration.html b/docs/tooling-integration.html index 343739aea5..41d45f62a6 100644 --- a/docs/tooling-integration.html +++ b/docs/tooling-integration.html @@ -316,6 +316,27 @@ + + diff --git a/docs/top-level-api.html b/docs/top-level-api.html index 6b1dc39ae5..2fd995fad8 100644 --- a/docs/top-level-api.html +++ b/docs/top-level-api.html @@ -316,6 +316,27 @@ + + diff --git a/docs/tutorial.html b/docs/tutorial.html index 013215f539..e677d20fe0 100644 --- a/docs/tutorial.html +++ b/docs/tutorial.html @@ -316,6 +316,27 @@ + + diff --git a/docs/two-way-binding-helpers.html b/docs/two-way-binding-helpers.html index 046c50ab9c..b7e75b592b 100644 --- a/docs/two-way-binding-helpers.html +++ b/docs/two-way-binding-helpers.html @@ -316,6 +316,27 @@ + + diff --git a/docs/update.html b/docs/update.html index 1b23006e91..900849a9a5 100644 --- a/docs/update.html +++ b/docs/update.html @@ -316,6 +316,27 @@ + + diff --git a/docs/videos.html b/docs/videos.html index cede9e5c30..658b7b0f92 100644 --- a/docs/videos.html +++ b/docs/videos.html @@ -316,6 +316,27 @@ + + diff --git a/docs/why-react.html b/docs/why-react.html index 81f428e6d7..5cd9efb621 100644 --- a/docs/why-react.html +++ b/docs/why-react.html @@ -316,6 +316,27 @@ + + diff --git a/docs/working-with-the-browser.html b/docs/working-with-the-browser.html index 85d6d709d1..27863dad96 100644 --- a/docs/working-with-the-browser.html +++ b/docs/working-with-the-browser.html @@ -316,6 +316,27 @@ + + diff --git a/feed.xml b/feed.xml index 2688802729..3329a78bfb 100644 --- a/feed.xml +++ b/feed.xml @@ -6,6 +6,25 @@ http://facebook.github.io/react + + Flux: An Application Architecture for React + <p>We recently spoke at one of f8&#39;s breakout session about Flux, a data flow architecture that works well with React. Check out the video here:</p> + +<figure><iframe width="560" height="315" src="//www.youtube.com/embed/nYkdrAPrdcw?list=PLb0IAmt7-GS188xDYE-u1ShQmFFGbrk0v" frameborder="0" allowfullscreen></iframe></figure> + +<p>To summarize, Flux works well for us because the single directional data flow makes it easy to understand and modify an application as it becomes more complicated. We found that two-way data bindings lead to cascading updates, where changing one data model led to another data model updating, making it very difficult to predict what would change as the result of a single user interaction.</p> + +<p>In Flux, the Dispatcher is a singleton that directs the flow of data and ensures that updates do not cascade. As an application grows, the Dispatcher becomes more vital, as it can also manage dependencies between stores by invoking the registered callbacks in a specific order.</p> + +<p>When a user interacts with a React view, the view sends an action (usually represented as a JavaScript object with some fields) through the dispatcher, which notifies the various stores that hold the application&#39;s data and business logic. When the stores change state, they notify the views that something has updated. This works especially well with React&#39;s declarative model, which allows the stores to send updates without specifying how to transition views between states.</p> + +<p>Flux is more of a pattern than a formal framework, so you can start using Flux immediately without a lot of new code. An <a href="https://github.com/facebook/react/tree/master/examples/todomvc-flux">example of this architecture</a> is available, along with more <a href="http://facebook.github.io/react/docs/flux-overview.html">detailed documentation</a> and a <a href="http://facebook.github.io/react/docs/flux/flux-todo-list.html">tutorial</a>. Look for more examples to come in the future.</p> + + 2014-05-06T00:00:00-07:00 + http://facebook.github.io/react/blog/2014/05/06/flux.html + http://facebook.github.io/react/blog/2014/05/06/flux.html + + Use React and JSX in ASP.NET MVC <p>Today we&#39;re happy to announce the initial release of @@ -687,116 +706,5 @@ Minified build for production: <a href="http://fb.me/react-with-addons-0 http://facebook.github.io/react/blog/2014/02/15/community-roundup-16.html - - Community Round-up #15 - <p>Interest in React seems to have surged ever since David Nolen (<a href="https://twitter.com/swannodette">@swannodette</a>)&#39;s introduction of <a href="https://github.com/swannodette/om">Om</a> in his post <a href="http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/">&quot;The Future of Javascript MVC Frameworks&quot;</a>.</p> - -<p>In this React Community Round-up, we are taking a closer look at React from a functional programming perspective.</p> -<h2><a class="anchor" name="react-another-level-of-indirection"></a>&quot;React: Another Level of Indirection&quot; <a class="hash-link" href="#react-another-level-of-indirection">#</a></h2> -<p>To start things off, Eric Normand (<a href="https://twitter.com/ericnormand">@ericnormand</a>) of <a href="http://lispcast.com">LispCast</a> makes the case for <a href="http://www.lispcast.com/react-another-level-of-indirection">React from a general functional programming standpoint</a> and explains how React&#39;s &quot;Virtual DOM provides the last piece of the Web Frontend Puzzle for ClojureScript&quot;.</p> - -<blockquote> -<p>The Virtual DOM is an indirection mechanism that solves the difficult problem of DOM programming: how to deal with incremental changes to a stateful tree structure. By abstracting away the statefulness, the Virtual DOM turns the real DOM into an immediate mode GUI, which is perfect for functional programming.</p> - -<p><a href="http://www.lispcast.com/react-another-level-of-indirection">Read the full post...</a></p> -</blockquote> -<h2><a class="anchor" name="reagent-minimalistic-react-for-clojurescript"></a>Reagent: Minimalistic React for ClojureScript <a class="hash-link" href="#reagent-minimalistic-react-for-clojurescript">#</a></h2> -<p>Dan Holmsand (<a href="https://twitter.com/holmsand">@holmsand</a>) created <a href="http://holmsand.github.io/reagent/">Reagent</a>, a simplistic ClojureScript API to React.</p> - -<blockquote> -<p>It allows you to define efficient React components using nothing but plain ClojureScript functions and data, that describe your UI using a Hiccup-like syntax.</p> - -<p>The goal of Reagent is to make it possible to define arbitrarily complex UIs using just a couple of basic concepts, and to be fast enough by default that you rarely have to care about performance.</p> - -<p><a href="http://holmsand.github.io/reagent/">Check it out on Github...</a></p> -</blockquote> -<h2><a class="anchor" name="functional-dom-programming"></a>Functional DOM programming <a class="hash-link" href="#functional-dom-programming">#</a></h2> -<p>React&#39;s one-way data-binding naturally lends itself to a functional programming approach. Facebook&#39;s Pete Hunt (<a href="https://twitter.com/floydophone">@floydophone</a>) explores how one would go about <a href="https://medium.com/p/67d81637d43">writing web apps in a functional manner</a>. Spoiler alert:</p> - -<blockquote> -<p>This is React. It’s not about templates, or data binding, or DOM manipulation. It’s about using functional programming with a virtual DOM representation to build ambitious, high-performance apps with JavaScript.</p> - -<p><a href="https://medium.com/p/67d81637d43">Read the full post...</a></p> -</blockquote> - -<p>Pete also explains this in detail at his #MeteorDevShop talk (about 30 Minutes):</p> - -<iframe width="560" height="315" src="//www.youtube.com/embed/Lqcs6hPOcFw?start=2963" frameborder="0" allowfullscreen></iframe> -<h2><a class="anchor" name="kioo-separating-markup-and-logic"></a>Kioo: Separating markup and logic <a class="hash-link" href="#kioo-separating-markup-and-logic">#</a></h2> -<p><a href="https://github.com/ckirkendall">Creighton Kirkendall</a> created <a href="https://github.com/ckirkendall/kioo">Kioo</a>, which adds Enlive-style templating to React. HTML templates are separated from the application logic. Kioo comes with separate examples for both Om and Reagent.</p> - -<p>A basic example from github:</p> -<div class="highlight"><pre><code class="html language-html" data-lang="html"><span class="cp">&lt;!DOCTYPE html&gt;</span> -<span class="nt">&lt;html</span> <span class="na">lang=</span><span class="s">&quot;en&quot;</span><span class="nt">&gt;</span> - <span class="nt">&lt;body&gt;</span> - <span class="nt">&lt;header&gt;</span> - <span class="nt">&lt;h1&gt;</span>Header placeholder<span class="nt">&lt;/h1&gt;</span> - <span class="nt">&lt;ul</span> <span class="na">id=</span><span class="s">&quot;navigation&quot;</span><span class="nt">&gt;</span> - <span class="nt">&lt;li</span> <span class="na">class=</span><span class="s">&quot;nav-item&quot;</span><span class="nt">&gt;&lt;a</span> <span class="na">href=</span><span class="s">&quot;#&quot;</span><span class="nt">&gt;</span>Placeholder<span class="nt">&lt;/a&gt;&lt;/li&gt;</span> - <span class="nt">&lt;/ul&gt;</span> - <span class="nt">&lt;/header&gt;</span> - <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;content&quot;</span><span class="nt">&gt;</span>place holder<span class="nt">&lt;/div&gt;</span> - <span class="nt">&lt;/body&gt;</span> -<span class="nt">&lt;/html&gt;</span> -</code></pre></div><div class="highlight"><pre><code class="clojure language-clojure" data-lang="clojure"><span class="nv">...</span> - -<span class="p">(</span><span class="kd">defn </span><span class="nv">my-nav-item</span> <span class="p">[[</span><span class="nv">caption</span> <span class="nv">func</span><span class="p">]]</span> - <span class="p">(</span><span class="nf">kioo/component</span> <span class="s">&quot;main.html&quot;</span> <span class="p">[</span><span class="ss">:.nav-item</span><span class="p">]</span> - <span class="p">{[</span><span class="ss">:a</span><span class="p">]</span> <span class="p">(</span><span class="nf">do-&gt;</span> <span class="p">(</span><span class="nf">content</span> <span class="nv">caption</span><span class="p">)</span> - <span class="p">(</span><span class="nf">set-attr</span> <span class="ss">:onClick</span> <span class="nv">func</span><span class="p">))}))</span> - -<span class="p">(</span><span class="kd">defn </span><span class="nv">my-header</span> <span class="p">[</span><span class="nv">heading</span> <span class="nv">nav-elms</span><span class="p">]</span> - <span class="p">(</span><span class="nf">kioo/component</span> <span class="s">&quot;main.html&quot;</span> <span class="p">[</span><span class="ss">:header</span><span class="p">]</span> - <span class="p">{[</span><span class="ss">:h1</span><span class="p">]</span> <span class="p">(</span><span class="nf">content</span> <span class="nv">heading</span><span class="p">)</span> - <span class="p">[</span><span class="ss">:ul</span><span class="p">]</span> <span class="p">(</span><span class="nf">content</span> <span class="p">(</span><span class="nb">map </span><span class="nv">my-nav-item</span> <span class="nv">nav-elms</span><span class="p">))}))</span> - -<span class="p">(</span><span class="kd">defn </span><span class="nv">my-page</span> <span class="p">[</span><span class="nv">data</span><span class="p">]</span> - <span class="p">(</span><span class="nf">kioo/component</span> <span class="s">&quot;main.html&quot;</span> - <span class="p">{[</span><span class="ss">:header</span><span class="p">]</span> <span class="p">(</span><span class="nf">substitute</span> <span class="p">(</span><span class="nf">my-header</span> <span class="p">(</span><span class="ss">:heading</span> <span class="nv">data</span><span class="p">)</span> - <span class="p">(</span><span class="ss">:navigation</span> <span class="nv">data</span><span class="p">)))</span> - <span class="p">[</span><span class="ss">:.content</span><span class="p">]</span> <span class="p">(</span><span class="nf">content</span> <span class="p">(</span><span class="ss">:content</span> <span class="nv">data</span><span class="p">))}))</span> - -<span class="p">(</span><span class="k">def </span><span class="nv">app-state</span> <span class="p">(</span><span class="nf">atom</span> <span class="p">{</span><span class="ss">:heading</span> <span class="s">&quot;main&quot;</span> - <span class="ss">:content</span> <span class="s">&quot;Hello World&quot;</span> - <span class="ss">:navigation</span> <span class="p">[[</span><span class="s">&quot;home&quot;</span> <span class="o">#</span><span class="p">(</span><span class="nf">js/alert</span> <span class="nv">%</span><span class="p">)]</span> - <span class="p">[</span><span class="s">&quot;next&quot;</span> <span class="o">#</span><span class="p">(</span><span class="nf">js/alert</span> <span class="nv">%</span><span class="p">)]]}))</span> - -<span class="p">(</span><span class="nf">om/root</span> <span class="nv">app-state</span> <span class="nv">my-page</span> <span class="p">(</span><span class="nf">.-body</span> <span class="nv">js/document</span><span class="p">))</span> -</code></pre></div><h2><a class="anchor" name="om"></a>Om <a class="hash-link" href="#om">#</a></h2> -<p>In an interview with David Nolen, Tom Coupland (<a href="https://twitter.com/tcoupland">@tcoupland</a>) of InfoQ provides a nice summary of recent developments around Om (&quot;<a href="http://www.infoq.com/news/2014/01/om-react">Om: Enhancing Facebook&#39;s React with Immutability</a>&quot;).</p> - -<blockquote> -<p>David [Nolen]: I think people are starting to see the limitations of just JavaScript and jQuery and even more structured solutions like Backbone, Angular, Ember, etc. React is a fresh approach to the DOM problem that seems obvious in hindsight.</p> - -<p><a href="http://www.infoq.com/news/2014/01/om-react">Read the full interview...</a></p> -</blockquote> -<h3><a class="anchor" name="a-slice-of-react-clojurescript-and-om"></a>A slice of React, ClojureScript and Om <a class="hash-link" href="#a-slice-of-react-clojurescript-and-om">#</a></h3> -<p>Fredrik Dyrkell (<a href="https://twitter.com/lexicallyscoped">@lexicallyscoped</a>) rewrote part of the <a href="http://www.lexicallyscoped.com/2013/12/25/slice-of-reactjs-and-cljs.html">React tutorial in both ClojureScript and Om</a>, along with short, helpful explanations.</p> - -<blockquote> -<p>React has sparked a lot of interest in the Clojure community lately [...]. At the very core, React lets you build up your DOM representation in a functional fashion by composing pure functions and you have a simple building block for everything: React components.</p> - -<p><a href="http://www.lexicallyscoped.com/2013/12/25/slice-of-reactjs-and-cljs.html">Read the full post...</a></p> -</blockquote> - -<p>In a separate post, Dyrkell breaks down <a href="http://www.lexicallyscoped.com/2014/01/23/ClojureScript-react-om-binary-clock.html">how to build a binary clock component</a> in Om.</p> - -<p>[<a href="http://www.lexicallyscoped.com/demo/binclock/">Demo</a>] [<a href="https://github.com/fredyr/binclock/blob/master/src/binclock/core.cljs">Code</a>]</p> -<h3><a class="anchor" name="time-travel-implementing-undo-in-om"></a>Time Travel: Implementing undo in Om <a class="hash-link" href="#time-travel-implementing-undo-in-om">#</a></h3> -<p>David Nolen shows how to leverage immutable data structures to <a href="http://swannodette.github.io/2013/12/31/time-travel/">add global undo</a> functionality to an app – using just 13 lines of ClojureScript.</p> -<h3><a class="anchor" name="a-step-by-step-om-walkthrough"></a>A Step-by-Step Om Walkthrough <a class="hash-link" href="#a-step-by-step-om-walkthrough">#</a></h3> -<p><a href="http://www.joshlehman.me">Josh Lehman</a> took the time to create an extensive <a href="http://www.joshlehman.me/rewriting-the-react-tutorial-in-om/">step-by-step walkthrough</a> of the React tutorial in Om. The well-documented source is on <a href="https://github.com/jalehman/omtut-starter">github</a>.</p> -<h3><a class="anchor" name="omkara"></a>Omkara <a class="hash-link" href="#omkara">#</a></h3> -<p><a href="https://github.com/brendanyounger">brendanyounger</a> created <a href="https://github.com/brendanyounger/omkara">omkara</a>, a starting point for ClojureScript web apps based on Om/React. It aims to take advantage of server-side rendering and comes with a few tips on getting started with Om/React projects.</p> -<h3><a class="anchor" name="om-experience-report"></a>Om Experience Report <a class="hash-link" href="#om-experience-report">#</a></h3> -<p>Adam Solove (<a href="https://twitter.com/asolove/">@asolove</a>) <a href="http://adamsolove.com/js/clojure/2014/01/06/om-experience-report.html">dives a little deeper into Om, React and ClojureScript</a>. He shares some helpful tips he gathered while building his <a href="https://github.com/asolove/carto-crayon">CartoCrayon</a> prototype.</p> -<h2><a class="anchor" name="not-so-random-tweet"></a>Not-so-random Tweet <a class="hash-link" href="#not-so-random-tweet">#</a></h2> -<div><blockquote class="twitter-tweet" lang="en"><p>[@swannodette](https://twitter.com/swannodette) No thank you! It's honestly a bit weird because Om is exactly what I didn't know I wanted for doing functional UI work.</p>&mdash; Adam Solove (@asolove) <a href="https://twitter.com/asolove/status/420294067637858304">January 6, 2014</a></blockquote></div> - - 2014-02-05T00:00:00-08:00 - http://facebook.github.io/react/blog/2014/02/05/community-roundup-15.html - http://facebook.github.io/react/blog/2014/02/05/community-roundup-15.html - - diff --git a/tips/children-props-type.html b/tips/children-props-type.html index 887cede51e..fc15b72aa3 100644 --- a/tips/children-props-type.html +++ b/tips/children-props-type.html @@ -316,6 +316,27 @@ + + diff --git a/tips/communicate-between-components.html b/tips/communicate-between-components.html index 426094c51a..12fb69581f 100644 --- a/tips/communicate-between-components.html +++ b/tips/communicate-between-components.html @@ -316,6 +316,27 @@ + + diff --git a/tips/componentWillReceiveProps-not-triggered-after-mounting.html b/tips/componentWillReceiveProps-not-triggered-after-mounting.html index 14ed1aabd4..8370f6c280 100644 --- a/tips/componentWillReceiveProps-not-triggered-after-mounting.html +++ b/tips/componentWillReceiveProps-not-triggered-after-mounting.html @@ -316,6 +316,27 @@ + + diff --git a/tips/controlled-input-null-value.html b/tips/controlled-input-null-value.html index 2f9d868a8e..48164d356e 100644 --- a/tips/controlled-input-null-value.html +++ b/tips/controlled-input-null-value.html @@ -316,6 +316,27 @@ + + diff --git a/tips/dom-event-listeners.html b/tips/dom-event-listeners.html index deda58f8ed..630eb72821 100644 --- a/tips/dom-event-listeners.html +++ b/tips/dom-event-listeners.html @@ -316,6 +316,27 @@ + + diff --git a/tips/expose-component-functions.html b/tips/expose-component-functions.html index d2ec2bf510..dcf4532bd3 100644 --- a/tips/expose-component-functions.html +++ b/tips/expose-component-functions.html @@ -316,6 +316,27 @@ + + diff --git a/tips/false-in-jsx.html b/tips/false-in-jsx.html index f6c5e51283..83e985367b 100644 --- a/tips/false-in-jsx.html +++ b/tips/false-in-jsx.html @@ -316,6 +316,27 @@ + + diff --git a/tips/if-else-in-JSX.html b/tips/if-else-in-JSX.html index ed5001493e..6a869e9159 100644 --- a/tips/if-else-in-JSX.html +++ b/tips/if-else-in-JSX.html @@ -316,6 +316,27 @@ + + diff --git a/tips/initial-ajax.html b/tips/initial-ajax.html index 96d0e6754c..f77df5f3d6 100644 --- a/tips/initial-ajax.html +++ b/tips/initial-ajax.html @@ -316,6 +316,27 @@ + + diff --git a/tips/inline-styles.html b/tips/inline-styles.html index 799ffea46e..e68a52391a 100644 --- a/tips/inline-styles.html +++ b/tips/inline-styles.html @@ -316,6 +316,27 @@ + + diff --git a/tips/introduction.html b/tips/introduction.html index 92635531fa..e689db7755 100644 --- a/tips/introduction.html +++ b/tips/introduction.html @@ -316,6 +316,27 @@ + + diff --git a/tips/maximum-number-of-jsx-root-nodes.html b/tips/maximum-number-of-jsx-root-nodes.html index 2b9f5b8213..0ca9adc8d8 100644 --- a/tips/maximum-number-of-jsx-root-nodes.html +++ b/tips/maximum-number-of-jsx-root-nodes.html @@ -316,6 +316,27 @@ + + diff --git a/tips/props-in-getInitialState-as-anti-pattern.html b/tips/props-in-getInitialState-as-anti-pattern.html index 3aeb013d01..d1bb499205 100644 --- a/tips/props-in-getInitialState-as-anti-pattern.html +++ b/tips/props-in-getInitialState-as-anti-pattern.html @@ -316,6 +316,27 @@ + + diff --git a/tips/references-to-components.html b/tips/references-to-components.html index 9a458542aa..f2e9d2b01c 100644 --- a/tips/references-to-components.html +++ b/tips/references-to-components.html @@ -316,6 +316,27 @@ + + diff --git a/tips/self-closing-tag.html b/tips/self-closing-tag.html index 11d2a86912..6136264b8b 100644 --- a/tips/self-closing-tag.html +++ b/tips/self-closing-tag.html @@ -316,6 +316,27 @@ + + diff --git a/tips/style-props-value-px.html b/tips/style-props-value-px.html index e0830cb298..eeb31cab7f 100644 --- a/tips/style-props-value-px.html +++ b/tips/style-props-value-px.html @@ -316,6 +316,27 @@ + +