From 58ccca7f752cc17358ffc3caf35eb455766d1f0a Mon Sep 17 00:00:00 2001 From: Travis CI Date: Fri, 8 Jan 2016 18:33:53 +0000 Subject: [PATCH] Rebuild website --- blog/2013/06/02/jsfiddle-integration.html | 4 +- blog/2013/06/05/why-react.html | 4 +- blog/2013/06/12/community-roundup.html | 4 +- blog/2013/06/19/community-roundup-2.html | 4 +- blog/2013/06/21/react-v0-3-3.html | 4 +- blog/2013/06/27/community-roundup-3.html | 4 +- .../07/02/react-v0-4-autobind-by-default.html | 4 +- blog/2013/07/03/community-roundup-4.html | 4 +- ...-4-prop-validation-and-default-values.html | 4 +- blog/2013/07/17/react-v0-4-0.html | 4 +- blog/2013/07/23/community-roundup-5.html | 4 +- blog/2013/07/26/react-v0-4-1.html | 4 +- .../use-react-and-jsx-in-ruby-on-rails.html | 4 +- blog/2013/08/05/community-roundup-6.html | 4 +- ...-react-and-jsx-in-python-applications.html | 4 +- blog/2013/08/26/community-roundup-7.html | 4 +- blog/2013/09/24/community-roundup-8.html | 4 +- blog/2013/10/03/community-roundup-9.html | 4 +- blog/2013/10/16/react-v0.5.0.html | 4 +- blog/2013/10/29/react-v0-5-1.html | 4 +- blog/2013/11/06/community-roundup-10.html | 4 +- blog/2013/11/18/community-roundup-11.html | 4 +- blog/2013/12/18/react-v0.5.2-v0.4.2.html | 4 +- blog/2013/12/19/react-v0.8.0.html | 4 +- blog/2013/12/23/community-roundup-12.html | 4 +- blog/2013/12/30/community-roundup-13.html | 4 +- .../01/02/react-chrome-developer-tools.html | 4 +- blog/2014/01/06/community-roundup-14.html | 4 +- blog/2014/02/05/community-roundup-15.html | 4 +- blog/2014/02/15/community-roundup-16.html | 4 +- blog/2014/02/16/react-v0.9-rc1.html | 4 +- blog/2014/02/20/react-v0.9.html | 4 +- blog/2014/02/24/community-roundup-17.html | 4 +- blog/2014/03/14/community-roundup-18.html | 4 +- blog/2014/03/19/react-v0.10-rc1.html | 4 +- blog/2014/03/21/react-v0.10.html | 4 +- blog/2014/03/28/the-road-to-1.0.html | 4 +- blog/2014/04/04/reactnet.html | 4 +- blog/2014/05/06/flux.html | 4 +- .../05/29/one-year-of-open-source-react.html | 4 +- blog/2014/06/27/community-roundup-19.html | 4 +- blog/2014/07/13/react-v0.11-rc1.html | 4 +- blog/2014/07/17/react-v0.11.html | 4 +- blog/2014/07/25/react-v0.11.1.html | 4 +- blog/2014/07/28/community-roundup-20.html | 4 +- .../30/flux-actions-and-the-dispatcher.html | 4 +- blog/2014/08/03/community-roundup-21.html | 4 +- .../03/introducing-the-jsx-specification.html | 4 +- blog/2014/09/12/community-round-up-22.html | 4 +- blog/2014/09/16/react-v0.11.2.html | 4 +- .../2014/09/24/testing-flux-applications.html | 4 +- .../10/14/introducing-react-elements.html | 4 +- blog/2014/10/16/react-v0.12-rc1.html | 4 +- blog/2014/10/17/community-roundup-23.html | 4 +- blog/2014/10/27/react-js-conf.html | 4 +- blog/2014/10/28/react-v0.12.html | 4 +- blog/2014/11/24/react-js-conf-updates.html | 4 +- blog/2014/11/25/community-roundup-24.html | 4 +- blog/2014/12/18/react-v0.12.2.html | 4 +- .../react-js-conf-diversity-scholarship.html | 4 +- blog/2015/01/27/react-v0.13.0-beta-1.html | 4 +- blog/2015/02/18/react-conf-roundup-2015.html | 4 +- .../02/20/introducing-relay-and-graphql.html | 4 +- blog/2015/02/24/react-v0.13-rc1.html | 4 +- .../02/24/streamlining-react-elements.html | 4 +- blog/2015/03/03/react-v0.13-rc2.html | 4 +- blog/2015/03/04/community-roundup-25.html | 4 +- blog/2015/03/10/react-v0.13.html | 4 +- blog/2015/03/16/react-v0.13.1.html | 4 +- ...ing-the-facebook-news-feed-with-relay.html | 4 +- blog/2015/03/26/introducing-react-native.html | 4 +- blog/2015/03/30/community-roundup-26.html | 4 +- blog/2015/04/17/react-native-v0.4.html | 4 +- blog/2015/04/18/react-v0.13.2.html | 4 +- blog/2015/05/01/graphql-introduction.html | 4 +- blog/2015/05/08/react-v0.13.3.html | 4 +- .../05/22/react-native-release-process.html | 4 +- ...precating-jstransform-and-react-tools.html | 4 +- blog/2015/07/03/react-v0.14-beta-1.html | 4 +- blog/2015/08/03/new-react-devtools-beta.html | 4 +- blog/2015/08/11/relay-technical-preview.html | 4 +- blog/2015/08/13/reacteurope-roundup.html | 4 +- .../2015/09/02/new-react-developer-tools.html | 4 +- blog/2015/09/10/react-v0.14-rc1.html | 4 +- blog/2015/09/14/community-roundup-27.html | 4 +- .../10/01/react-render-and-top-level-api.html | 4 +- blog/2015/10/07/react-v0.14.html | 4 +- .../19/reactiflux-is-moving-to-discord.html | 4 +- blog/2015/10/28/react-v0.14.1.html | 4 +- blog/2015/11/02/react-v0.14.2.html | 4 +- blog/2015/11/18/react-v0.14.3.html | 4 +- ...ct-js-conf-2016-diversity-scholarship.html | 4 +- blog/2015/12/16/ismounted-antipattern.html | 4 +- ...act-components-elements-and-instances.html | 4 +- blog/2015/12/29/react-v0.14.4.html | 4 +- ...-implies-B-does-not-imply-B-implies-A.html | 211 +++++++++ blog/all.html | 7 + blog/index.html | 153 +++--- blog/page10/index.html | 354 +++++++++++--- blog/page11/index.html | 131 +++--- blog/page12/index.html | 171 +++---- blog/page13/index.html | 246 ++++------ blog/page14/index.html | 269 ++++++----- blog/page15/index.html | 260 +++++------ blog/page16/index.html | 245 +++++----- blog/page17/index.html | 226 +++++---- blog/page18/index.html | 227 ++++----- blog/page19/index.html | 147 ++++-- blog/page2/index.html | 215 +++------ blog/page20/index.html | 177 +++++++ blog/page3/index.html | 201 +++++--- blog/page4/index.html | 122 +++-- blog/page5/index.html | 110 +++-- blog/page6/index.html | 125 ++--- blog/page7/index.html | 239 ++++------ blog/page8/index.html | 303 ++++++------ blog/page9/index.html | 441 ++++++------------ docs/component-specs.html | 2 + docs/forms.html | 2 +- docs/reconciliation.html | 2 +- docs/test-utils.html | 3 +- docs/thinking-in-react-ko-KR.html | 6 +- docs/thinking-in-react.html | 6 +- docs/thinking-in-react.it-IT.html | 6 +- docs/thinking-in-react.zh-CN.html | 116 ++--- feed.xml | 173 +++---- 126 files changed, 2833 insertions(+), 2443 deletions(-) create mode 100644 blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html create mode 100644 blog/page20/index.html diff --git a/blog/2013/06/02/jsfiddle-integration.html b/blog/2013/06/02/jsfiddle-integration.html index 36c0b984f0..2278b4c535 100644 --- a/blog/2013/06/02/jsfiddle-integration.html +++ b/blog/2013/06/02/jsfiddle-integration.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/06/05/why-react.html b/blog/2013/06/05/why-react.html index 8b7fd91caa..4c1485580f 100644 --- a/blog/2013/06/05/why-react.html +++ b/blog/2013/06/05/why-react.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/06/12/community-roundup.html b/blog/2013/06/12/community-roundup.html index f6a93476ce..9b5cf0ace8 100644 --- a/blog/2013/06/12/community-roundup.html +++ b/blog/2013/06/12/community-roundup.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/06/19/community-roundup-2.html b/blog/2013/06/19/community-roundup-2.html index f01e3bcd66..2f5cdbabbc 100644 --- a/blog/2013/06/19/community-roundup-2.html +++ b/blog/2013/06/19/community-roundup-2.html @@ -67,6 +67,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 fa49f85ab7..75582cf01f 100644 --- a/blog/2013/06/21/react-v0-3-3.html +++ b/blog/2013/06/21/react-v0-3-3.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/06/27/community-roundup-3.html b/blog/2013/06/27/community-roundup-3.html index 974b4d75fa..2980d931e0 100644 --- a/blog/2013/06/27/community-roundup-3.html +++ b/blog/2013/06/27/community-roundup-3.html @@ -67,6 +67,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 f73e2dbddf..ad8934173a 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 @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/07/03/community-roundup-4.html b/blog/2013/07/03/community-roundup-4.html index 425525de7a..67bc1559d7 100644 --- a/blog/2013/07/03/community-roundup-4.html +++ b/blog/2013/07/03/community-roundup-4.html @@ -67,6 +67,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 ad64db7e51..34018a8688 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 @@ -67,6 +67,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 68e13c4828..afd2844620 100644 --- a/blog/2013/07/17/react-v0-4-0.html +++ b/blog/2013/07/17/react-v0-4-0.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/07/23/community-roundup-5.html b/blog/2013/07/23/community-roundup-5.html index aecb215701..bdffbe7c9d 100644 --- a/blog/2013/07/23/community-roundup-5.html +++ b/blog/2013/07/23/community-roundup-5.html @@ -67,6 +67,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 6b429b0ee4..7934d694e3 100644 --- a/blog/2013/07/26/react-v0-4-1.html +++ b/blog/2013/07/26/react-v0-4-1.html @@ -67,6 +67,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 85a7c84a30..6d1807202c 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 @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/08/05/community-roundup-6.html b/blog/2013/08/05/community-roundup-6.html index 55373d03bb..a7d0b24613 100644 --- a/blog/2013/08/05/community-roundup-6.html +++ b/blog/2013/08/05/community-roundup-6.html @@ -67,6 +67,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 31328b81e2..94984b62e2 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 @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/08/26/community-roundup-7.html b/blog/2013/08/26/community-roundup-7.html index 9af02f12cd..b36db3c5bb 100644 --- a/blog/2013/08/26/community-roundup-7.html +++ b/blog/2013/08/26/community-roundup-7.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/09/24/community-roundup-8.html b/blog/2013/09/24/community-roundup-8.html index d70caf4021..a9313a73d7 100644 --- a/blog/2013/09/24/community-roundup-8.html +++ b/blog/2013/09/24/community-roundup-8.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/10/03/community-roundup-9.html b/blog/2013/10/03/community-roundup-9.html index cd2591ebdd..b687676611 100644 --- a/blog/2013/10/03/community-roundup-9.html +++ b/blog/2013/10/03/community-roundup-9.html @@ -67,6 +67,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 8beab3f07e..3f2b932b67 100644 --- a/blog/2013/10/16/react-v0.5.0.html +++ b/blog/2013/10/16/react-v0.5.0.html @@ -67,6 +67,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 5c0e80095a..0f58ed5687 100644 --- a/blog/2013/10/29/react-v0-5-1.html +++ b/blog/2013/10/29/react-v0-5-1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/11/06/community-roundup-10.html b/blog/2013/11/06/community-roundup-10.html index 404e16d2f0..aa1846a8cc 100644 --- a/blog/2013/11/06/community-roundup-10.html +++ b/blog/2013/11/06/community-roundup-10.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/11/18/community-roundup-11.html b/blog/2013/11/18/community-roundup-11.html index f4097c18ff..8df81f81c0 100644 --- a/blog/2013/11/18/community-roundup-11.html +++ b/blog/2013/11/18/community-roundup-11.html @@ -67,6 +67,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 2a99bf3d39..17d294b420 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 @@ -67,6 +67,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 1c040e2b28..4919789254 100644 --- a/blog/2013/12/19/react-v0.8.0.html +++ b/blog/2013/12/19/react-v0.8.0.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/12/23/community-roundup-12.html b/blog/2013/12/23/community-roundup-12.html index 74e1a24ed9..a9eaecc297 100644 --- a/blog/2013/12/23/community-roundup-12.html +++ b/blog/2013/12/23/community-roundup-12.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2013/12/30/community-roundup-13.html b/blog/2013/12/30/community-roundup-13.html index 5a0babb835..7416b619c0 100644 --- a/blog/2013/12/30/community-roundup-13.html +++ b/blog/2013/12/30/community-roundup-13.html @@ -67,6 +67,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 4e5d0b0712..e745c04c3c 100644 --- a/blog/2014/01/02/react-chrome-developer-tools.html +++ b/blog/2014/01/02/react-chrome-developer-tools.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/01/06/community-roundup-14.html b/blog/2014/01/06/community-roundup-14.html index 87293690ff..8562946d5d 100644 --- a/blog/2014/01/06/community-roundup-14.html +++ b/blog/2014/01/06/community-roundup-14.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/02/05/community-roundup-15.html b/blog/2014/02/05/community-roundup-15.html index 67024712cd..87f52cc885 100644 --- a/blog/2014/02/05/community-roundup-15.html +++ b/blog/2014/02/05/community-roundup-15.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/02/15/community-roundup-16.html b/blog/2014/02/15/community-roundup-16.html index 7bb8058264..6c089bb22c 100644 --- a/blog/2014/02/15/community-roundup-16.html +++ b/blog/2014/02/15/community-roundup-16.html @@ -67,6 +67,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 254d49e399..97120e7894 100644 --- a/blog/2014/02/16/react-v0.9-rc1.html +++ b/blog/2014/02/16/react-v0.9-rc1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/02/20/react-v0.9.html b/blog/2014/02/20/react-v0.9.html index 9f5b9c418f..6a96eed64a 100644 --- a/blog/2014/02/20/react-v0.9.html +++ b/blog/2014/02/20/react-v0.9.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/02/24/community-roundup-17.html b/blog/2014/02/24/community-roundup-17.html index 5cf956614c..f5cfb770da 100644 --- a/blog/2014/02/24/community-roundup-17.html +++ b/blog/2014/02/24/community-roundup-17.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/03/14/community-roundup-18.html b/blog/2014/03/14/community-roundup-18.html index 228e2e18ef..794744b9bf 100644 --- a/blog/2014/03/14/community-roundup-18.html +++ b/blog/2014/03/14/community-roundup-18.html @@ -67,6 +67,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 a59b7f6fc5..559413089d 100644 --- a/blog/2014/03/19/react-v0.10-rc1.html +++ b/blog/2014/03/19/react-v0.10-rc1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/03/21/react-v0.10.html b/blog/2014/03/21/react-v0.10.html index 8aa95827df..f8473655c4 100644 --- a/blog/2014/03/21/react-v0.10.html +++ b/blog/2014/03/21/react-v0.10.html @@ -67,6 +67,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 057259fe5d..cf38c02f52 100644 --- a/blog/2014/03/28/the-road-to-1.0.html +++ b/blog/2014/03/28/the-road-to-1.0.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/04/04/reactnet.html b/blog/2014/04/04/reactnet.html index d4ec74b7e0..8bbb46bf2c 100644 --- a/blog/2014/04/04/reactnet.html +++ b/blog/2014/04/04/reactnet.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/05/06/flux.html b/blog/2014/05/06/flux.html index 7bf08869ae..1d8ff6db1e 100644 --- a/blog/2014/05/06/flux.html +++ b/blog/2014/05/06/flux.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/05/29/one-year-of-open-source-react.html b/blog/2014/05/29/one-year-of-open-source-react.html index d7e8308da1..d3079204d0 100644 --- a/blog/2014/05/29/one-year-of-open-source-react.html +++ b/blog/2014/05/29/one-year-of-open-source-react.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/06/27/community-roundup-19.html b/blog/2014/06/27/community-roundup-19.html index bc834e03db..4a3a64cf2e 100644 --- a/blog/2014/06/27/community-roundup-19.html +++ b/blog/2014/06/27/community-roundup-19.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/07/13/react-v0.11-rc1.html b/blog/2014/07/13/react-v0.11-rc1.html index f719e18e40..bb062eb555 100644 --- a/blog/2014/07/13/react-v0.11-rc1.html +++ b/blog/2014/07/13/react-v0.11-rc1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/07/17/react-v0.11.html b/blog/2014/07/17/react-v0.11.html index 9012ff8ddc..88d63f6b55 100644 --- a/blog/2014/07/17/react-v0.11.html +++ b/blog/2014/07/17/react-v0.11.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/07/25/react-v0.11.1.html b/blog/2014/07/25/react-v0.11.1.html index f5cb267839..5657aa0171 100644 --- a/blog/2014/07/25/react-v0.11.1.html +++ b/blog/2014/07/25/react-v0.11.1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/07/28/community-roundup-20.html b/blog/2014/07/28/community-roundup-20.html index a4e3ed9bee..2ea5da9cab 100644 --- a/blog/2014/07/28/community-roundup-20.html +++ b/blog/2014/07/28/community-roundup-20.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/07/30/flux-actions-and-the-dispatcher.html b/blog/2014/07/30/flux-actions-and-the-dispatcher.html index f710d56881..8814fdd2ef 100644 --- a/blog/2014/07/30/flux-actions-and-the-dispatcher.html +++ b/blog/2014/07/30/flux-actions-and-the-dispatcher.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/08/03/community-roundup-21.html b/blog/2014/08/03/community-roundup-21.html index 9aa422ed84..20b6d7eafd 100644 --- a/blog/2014/08/03/community-roundup-21.html +++ b/blog/2014/08/03/community-roundup-21.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/09/03/introducing-the-jsx-specification.html b/blog/2014/09/03/introducing-the-jsx-specification.html index 71fa4d331d..c18a4255da 100644 --- a/blog/2014/09/03/introducing-the-jsx-specification.html +++ b/blog/2014/09/03/introducing-the-jsx-specification.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/09/12/community-round-up-22.html b/blog/2014/09/12/community-round-up-22.html index 7e7f7f4654..2ac75abc4a 100644 --- a/blog/2014/09/12/community-round-up-22.html +++ b/blog/2014/09/12/community-round-up-22.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/09/16/react-v0.11.2.html b/blog/2014/09/16/react-v0.11.2.html index a8b5955643..ae3a343b83 100644 --- a/blog/2014/09/16/react-v0.11.2.html +++ b/blog/2014/09/16/react-v0.11.2.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/09/24/testing-flux-applications.html b/blog/2014/09/24/testing-flux-applications.html index b0e4151a2a..9c831b02e6 100644 --- a/blog/2014/09/24/testing-flux-applications.html +++ b/blog/2014/09/24/testing-flux-applications.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/10/14/introducing-react-elements.html b/blog/2014/10/14/introducing-react-elements.html index 21eea348c3..f6522bf1ff 100644 --- a/blog/2014/10/14/introducing-react-elements.html +++ b/blog/2014/10/14/introducing-react-elements.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/10/16/react-v0.12-rc1.html b/blog/2014/10/16/react-v0.12-rc1.html index 6cbfc6b37b..de76a9a8d9 100644 --- a/blog/2014/10/16/react-v0.12-rc1.html +++ b/blog/2014/10/16/react-v0.12-rc1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/10/17/community-roundup-23.html b/blog/2014/10/17/community-roundup-23.html index 3a3c822f2b..0b45e48950 100644 --- a/blog/2014/10/17/community-roundup-23.html +++ b/blog/2014/10/17/community-roundup-23.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/10/27/react-js-conf.html b/blog/2014/10/27/react-js-conf.html index 7f2c68cb64..696fc22cee 100644 --- a/blog/2014/10/27/react-js-conf.html +++ b/blog/2014/10/27/react-js-conf.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/10/28/react-v0.12.html b/blog/2014/10/28/react-v0.12.html index 6e89514a88..6596717119 100644 --- a/blog/2014/10/28/react-v0.12.html +++ b/blog/2014/10/28/react-v0.12.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/11/24/react-js-conf-updates.html b/blog/2014/11/24/react-js-conf-updates.html index 5d91ec599c..faddc1f106 100644 --- a/blog/2014/11/24/react-js-conf-updates.html +++ b/blog/2014/11/24/react-js-conf-updates.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/11/25/community-roundup-24.html b/blog/2014/11/25/community-roundup-24.html index 358cc2a8ed..8b41b7bbc9 100644 --- a/blog/2014/11/25/community-roundup-24.html +++ b/blog/2014/11/25/community-roundup-24.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/12/18/react-v0.12.2.html b/blog/2014/12/18/react-v0.12.2.html index 19a94a690b..d96c27aca0 100644 --- a/blog/2014/12/18/react-v0.12.2.html +++ b/blog/2014/12/18/react-v0.12.2.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2014/12/19/react-js-conf-diversity-scholarship.html b/blog/2014/12/19/react-js-conf-diversity-scholarship.html index 3c3677fdb9..433651a861 100644 --- a/blog/2014/12/19/react-js-conf-diversity-scholarship.html +++ b/blog/2014/12/19/react-js-conf-diversity-scholarship.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/01/27/react-v0.13.0-beta-1.html b/blog/2015/01/27/react-v0.13.0-beta-1.html index 0b0b922f65..a4f6cd4473 100644 --- a/blog/2015/01/27/react-v0.13.0-beta-1.html +++ b/blog/2015/01/27/react-v0.13.0-beta-1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/02/18/react-conf-roundup-2015.html b/blog/2015/02/18/react-conf-roundup-2015.html index 23f67bc393..7ae085d118 100644 --- a/blog/2015/02/18/react-conf-roundup-2015.html +++ b/blog/2015/02/18/react-conf-roundup-2015.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/02/20/introducing-relay-and-graphql.html b/blog/2015/02/20/introducing-relay-and-graphql.html index 1fcdffe261..6a0ea86d1a 100644 --- a/blog/2015/02/20/introducing-relay-and-graphql.html +++ b/blog/2015/02/20/introducing-relay-and-graphql.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/02/24/react-v0.13-rc1.html b/blog/2015/02/24/react-v0.13-rc1.html index 2b05461891..fda3bcb20d 100644 --- a/blog/2015/02/24/react-v0.13-rc1.html +++ b/blog/2015/02/24/react-v0.13-rc1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/02/24/streamlining-react-elements.html b/blog/2015/02/24/streamlining-react-elements.html index b1842b9217..543854e275 100644 --- a/blog/2015/02/24/streamlining-react-elements.html +++ b/blog/2015/02/24/streamlining-react-elements.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/03/react-v0.13-rc2.html b/blog/2015/03/03/react-v0.13-rc2.html index 24c3b4b788..7d77c13652 100644 --- a/blog/2015/03/03/react-v0.13-rc2.html +++ b/blog/2015/03/03/react-v0.13-rc2.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/04/community-roundup-25.html b/blog/2015/03/04/community-roundup-25.html index fcb92b5bc6..edc7457a30 100644 --- a/blog/2015/03/04/community-roundup-25.html +++ b/blog/2015/03/04/community-roundup-25.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/10/react-v0.13.html b/blog/2015/03/10/react-v0.13.html index 87098b019b..d92be9797a 100644 --- a/blog/2015/03/10/react-v0.13.html +++ b/blog/2015/03/10/react-v0.13.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/16/react-v0.13.1.html b/blog/2015/03/16/react-v0.13.1.html index 1e902e6514..ecb80071b2 100644 --- a/blog/2015/03/16/react-v0.13.1.html +++ b/blog/2015/03/16/react-v0.13.1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/19/building-the-facebook-news-feed-with-relay.html b/blog/2015/03/19/building-the-facebook-news-feed-with-relay.html index 33ae3bf561..0f93ef0451 100644 --- a/blog/2015/03/19/building-the-facebook-news-feed-with-relay.html +++ b/blog/2015/03/19/building-the-facebook-news-feed-with-relay.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/26/introducing-react-native.html b/blog/2015/03/26/introducing-react-native.html index f946daa1d4..0a914e147f 100644 --- a/blog/2015/03/26/introducing-react-native.html +++ b/blog/2015/03/26/introducing-react-native.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/03/30/community-roundup-26.html b/blog/2015/03/30/community-roundup-26.html index 00c7623636..db9d3f923f 100644 --- a/blog/2015/03/30/community-roundup-26.html +++ b/blog/2015/03/30/community-roundup-26.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/04/17/react-native-v0.4.html b/blog/2015/04/17/react-native-v0.4.html index 54bd313f40..5688c51be2 100644 --- a/blog/2015/04/17/react-native-v0.4.html +++ b/blog/2015/04/17/react-native-v0.4.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/04/18/react-v0.13.2.html b/blog/2015/04/18/react-v0.13.2.html index 37b8faea6a..93ef7af14d 100644 --- a/blog/2015/04/18/react-v0.13.2.html +++ b/blog/2015/04/18/react-v0.13.2.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/05/01/graphql-introduction.html b/blog/2015/05/01/graphql-introduction.html index 24770f3826..6b512d3f89 100644 --- a/blog/2015/05/01/graphql-introduction.html +++ b/blog/2015/05/01/graphql-introduction.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/05/08/react-v0.13.3.html b/blog/2015/05/08/react-v0.13.3.html index 7254d2c5e1..1eb1adde15 100644 --- a/blog/2015/05/08/react-v0.13.3.html +++ b/blog/2015/05/08/react-v0.13.3.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/05/22/react-native-release-process.html b/blog/2015/05/22/react-native-release-process.html index 26d654252e..cd9c428780 100644 --- a/blog/2015/05/22/react-native-release-process.html +++ b/blog/2015/05/22/react-native-release-process.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/06/12/deprecating-jstransform-and-react-tools.html b/blog/2015/06/12/deprecating-jstransform-and-react-tools.html index 968045a9fe..fe30f1b174 100644 --- a/blog/2015/06/12/deprecating-jstransform-and-react-tools.html +++ b/blog/2015/06/12/deprecating-jstransform-and-react-tools.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/07/03/react-v0.14-beta-1.html b/blog/2015/07/03/react-v0.14-beta-1.html index 43b26e3c59..9629817806 100644 --- a/blog/2015/07/03/react-v0.14-beta-1.html +++ b/blog/2015/07/03/react-v0.14-beta-1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/08/03/new-react-devtools-beta.html b/blog/2015/08/03/new-react-devtools-beta.html index d7683e53de..ba536db423 100644 --- a/blog/2015/08/03/new-react-devtools-beta.html +++ b/blog/2015/08/03/new-react-devtools-beta.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/08/11/relay-technical-preview.html b/blog/2015/08/11/relay-technical-preview.html index d563308e40..c96c7592b8 100644 --- a/blog/2015/08/11/relay-technical-preview.html +++ b/blog/2015/08/11/relay-technical-preview.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/08/13/reacteurope-roundup.html b/blog/2015/08/13/reacteurope-roundup.html index a49fb98b3d..cd5f3f6584 100644 --- a/blog/2015/08/13/reacteurope-roundup.html +++ b/blog/2015/08/13/reacteurope-roundup.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/09/02/new-react-developer-tools.html b/blog/2015/09/02/new-react-developer-tools.html index 4d5aebe253..30efed5b86 100644 --- a/blog/2015/09/02/new-react-developer-tools.html +++ b/blog/2015/09/02/new-react-developer-tools.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/09/10/react-v0.14-rc1.html b/blog/2015/09/10/react-v0.14-rc1.html index 8a92f2609b..5460507f1e 100644 --- a/blog/2015/09/10/react-v0.14-rc1.html +++ b/blog/2015/09/10/react-v0.14-rc1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/09/14/community-roundup-27.html b/blog/2015/09/14/community-roundup-27.html index f13fda8574..e4c15b0300 100644 --- a/blog/2015/09/14/community-roundup-27.html +++ b/blog/2015/09/14/community-roundup-27.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/10/01/react-render-and-top-level-api.html b/blog/2015/10/01/react-render-and-top-level-api.html index 749f717575..18bddc4106 100644 --- a/blog/2015/10/01/react-render-and-top-level-api.html +++ b/blog/2015/10/01/react-render-and-top-level-api.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/10/07/react-v0.14.html b/blog/2015/10/07/react-v0.14.html index a95de8003b..80d7f7cacc 100644 --- a/blog/2015/10/07/react-v0.14.html +++ b/blog/2015/10/07/react-v0.14.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/10/19/reactiflux-is-moving-to-discord.html b/blog/2015/10/19/reactiflux-is-moving-to-discord.html index 47792f67a3..f7e122a03d 100644 --- a/blog/2015/10/19/reactiflux-is-moving-to-discord.html +++ b/blog/2015/10/19/reactiflux-is-moving-to-discord.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/10/28/react-v0.14.1.html b/blog/2015/10/28/react-v0.14.1.html index 348e9e2ede..913f373265 100644 --- a/blog/2015/10/28/react-v0.14.1.html +++ b/blog/2015/10/28/react-v0.14.1.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/11/02/react-v0.14.2.html b/blog/2015/11/02/react-v0.14.2.html index bdbbec3198..e8f0762c07 100644 --- a/blog/2015/11/02/react-v0.14.2.html +++ b/blog/2015/11/02/react-v0.14.2.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/11/18/react-v0.14.3.html b/blog/2015/11/18/react-v0.14.3.html index 11fb0096fe..bb59426c6f 100644 --- a/blog/2015/11/18/react-v0.14.3.html +++ b/blog/2015/11/18/react-v0.14.3.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/12/04/react-js-conf-2016-diversity-scholarship.html b/blog/2015/12/04/react-js-conf-2016-diversity-scholarship.html index f1e29868db..533cdfca53 100644 --- a/blog/2015/12/04/react-js-conf-2016-diversity-scholarship.html +++ b/blog/2015/12/04/react-js-conf-2016-diversity-scholarship.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/12/16/ismounted-antipattern.html b/blog/2015/12/16/ismounted-antipattern.html index dd8db60536..44f030c535 100644 --- a/blog/2015/12/16/ismounted-antipattern.html +++ b/blog/2015/12/16/ismounted-antipattern.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/12/18/react-components-elements-and-instances.html b/blog/2015/12/18/react-components-elements-and-instances.html index 6e87982153..902d7ed2a2 100644 --- a/blog/2015/12/18/react-components-elements-and-instances.html +++ b/blog/2015/12/18/react-components-elements-and-instances.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2015/12/29/react-v0.14.4.html b/blog/2015/12/29/react-v0.14.4.html index a5e33e41a6..a8e68b7e5f 100644 --- a/blog/2015/12/29/react-v0.14.4.html +++ b/blog/2015/12/29/react-v0.14.4.html @@ -67,6 +67,8 @@

Recent posts

diff --git a/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html b/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html new file mode 100644 index 0000000000..83cbf15c30 --- /dev/null +++ b/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html @@ -0,0 +1,211 @@ + + + + + + + (A => B) !=> (B => A) | React + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+ + +

+ + (A => B) !=> (B => A) + +

+ +

+ January 8, 2016 + by + + + Jim Sproch + + + +

+ +
+ +
+

The documentation for componentWillReceiveProps states that componentWillReceiveProps will be invoked when the props change as the result of a rerender. Some people assume this means "if componentWillReceiveProps is called, then the props must have changed", but that conclusion is logically incorrect.

+ +

The guiding principle is one of my favorites from formal logic/mathematics:

+ +
+

A implies B does not imply B implies A

+
+ +

Example: "If I eat moldy food, then I will get sick" does not imply "if I am sick, then I must have eaten moldy food". There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that componentWillReceiveProps might get called, even if the props didn’t change.

+ +

If you don’t believe me, call ReactDOM.render() three times with the exact same props, and try to predict the number of times componentWillReceiveProps will get called:

+
class Component extends React.Component {
+  componentWillReceiveProps(nextProps) {
+    console.log('componentWillReceiveProps', nextProps.data.bar);
+  }
+  render() {
+    return <div>Bar {this.props.data.bar}!</div>;
+  }
+}
+
+var container = document.getElementById('container');
+
+var mydata = {bar: 'drinks'};
+ReactDOM.render(<Component data={mydata} />, container);
+ReactDOM.render(<Component data={mydata} />, container);
+ReactDOM.render(<Component data={mydata} />, container);
+
+

In this case, the answer is "2". React calls componentWillReceiveProps twice (once for each of the two updates). Both times, the value of "drinks" is printed (ie. the props didn’t change).

+ +

To understand why, we need to think about what could have happened. The data could have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:

+
var mydata = {bar: 'drinks'};
+ReactDOM.render(<Component data={mydata} />, container);
+mydata.bar = 'food'
+ReactDOM.render(<Component data={mydata} />, container);
+mydata.bar = 'noise'
+ReactDOM.render(<Component data={mydata} />, container);
+
+

React has no way of knowing that the data didn’t change. Therefore, React needs to call componentWillReceiveProps, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).

+ +

You might think that React could just use smarter checks for equality, but there are some issues with this idea:

+ +
    +
  • The old mydata and the new mydata are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).
  • +
  • The mydata object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.
  • +
  • The mydata object might contain references to objects which are re-instantiated during the parent's render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.
  • +
+ +

Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call componentWillReceiveProps (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.

+ +

As a result, your implementation of componentWillReceiveProps MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your componentWillReceiveProps code needs to check to see if the props actually changed.

+ +
+ + +
+ + +
+
+ + +
+
+ A Facebook & Instagram collaboration.
+ Acknowledgements +
+
+ © 2013–2016 Facebook Inc.
+ Documentation licensed under CC BY 4.0. +
+
+
+
+ + + + diff --git a/blog/all.html b/blog/all.html index b43c2479f6..63bddb0cf6 100644 --- a/blog/all.html +++ b/blog/all.html @@ -65,6 +65,13 @@

All Posts

+

(A => B) !=> (B => A) on January 8, 2016 by + + Jim Sproch + + +

+

React v0.14.4 on December 29, 2015 by Ben Alpert diff --git a/blog/index.html b/blog/index.html index 0fafa6e2be..6a9194f130 100644 --- a/blog/index.html +++ b/blog/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,86 @@
+

+ + (A => B) !=> (B => A) + +

+ +

+ January 8, 2016 + by + + + Jim Sproch + + + +

+ +
+ +
+

The documentation for componentWillReceiveProps states that componentWillReceiveProps will be invoked when the props change as the result of a rerender. Some people assume this means "if componentWillReceiveProps is called, then the props must have changed", but that conclusion is logically incorrect.

+ +

The guiding principle is one of my favorites from formal logic/mathematics:

+ +
+

A implies B does not imply B implies A

+
+ +

Example: "If I eat moldy food, then I will get sick" does not imply "if I am sick, then I must have eaten moldy food". There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that componentWillReceiveProps might get called, even if the props didn’t change.

+ +

If you don’t believe me, call ReactDOM.render() three times with the exact same props, and try to predict the number of times componentWillReceiveProps will get called:

+
class Component extends React.Component {
+  componentWillReceiveProps(nextProps) {
+    console.log('componentWillReceiveProps', nextProps.data.bar);
+  }
+  render() {
+    return <div>Bar {this.props.data.bar}!</div>;
+  }
+}
+
+var container = document.getElementById('container');
+
+var mydata = {bar: 'drinks'};
+ReactDOM.render(<Component data={mydata} />, container);
+ReactDOM.render(<Component data={mydata} />, container);
+ReactDOM.render(<Component data={mydata} />, container);
+
+

In this case, the answer is "2". React calls componentWillReceiveProps twice (once for each of the two updates). Both times, the value of "drinks" is printed (ie. the props didn’t change).

+ +

To understand why, we need to think about what could have happened. The data could have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:

+
var mydata = {bar: 'drinks'};
+ReactDOM.render(<Component data={mydata} />, container);
+mydata.bar = 'food'
+ReactDOM.render(<Component data={mydata} />, container);
+mydata.bar = 'noise'
+ReactDOM.render(<Component data={mydata} />, container);
+
+

React has no way of knowing that the data didn’t change. Therefore, React needs to call componentWillReceiveProps, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).

+ +

You might think that React could just use smarter checks for equality, but there are some issues with this idea:

+ +
    +
  • The old mydata and the new mydata are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).
  • +
  • The mydata object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.
  • +
  • The mydata object might contain references to objects which are re-instantiated during the parent's render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.
  • +
+ +

Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call componentWillReceiveProps (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.

+ +

As a result, your implementation of componentWillReceiveProps MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your componentWillReceiveProps code needs to check to see if the props actually changed.

+ +
+ + + +
+ +
+ +

React v0.14.4 @@ -681,75 +761,6 @@ Minified build for production: - - -

- - React v0.14.3 - -

- -

- November 18, 2015 - by - - - Paul O’Shannessy - - - -

- -
- -
-

It's time for another installment of React patch releases! We didn't break anything in v0.14.2 but we do have a couple of other bugs we're fixing. The biggest change in this release is actually an addition of a new built file. We heard from a number of people that they still need the ability to use React to render to a string on the client. While the use cases are not common and there are other ways to achieve this, we decided that it's still valuable to support. So we're now building react-dom-server.js, which will be shipped to Bower and in the dist/ directory of the react-dom package on npm. This file works the same way as react-dom.js and therefore requires that the primary React build has already been included on the page.

- -

The release is now available for download:

- - - -

We've also published version 0.14.3 of the react, react-dom, and addons packages on npm and the react package on bower.

- -
-

Changelog #

React DOM #

-
    -
  • Added support for nonce attribute for <script> and <style> elements
  • -
  • Added support for reversed attribute for <ol> elements
  • -
-

React TestUtils Add-on #

-
    -
  • Fixed bug with shallow rendering and function refs
  • -
-

React CSSTransitionGroup Add-on #

-
    -
  • Fixed bug resulting in timeouts firing incorrectly when mounting and unmounting rapidly
  • -
-

React on Bower #

-
    -
  • Added react-dom-server.js to expose renderToString and renderToStaticMarkup for usage in the browser
  • -
- -
- - -

diff --git a/blog/page10/index.html b/blog/page10/index.html index be85e7076e..102b439ff2 100644 --- a/blog/page10/index.html +++ b/blog/page10/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,301 @@
+

+ + Testing Flux Applications + +

+ +

+ September 24, 2014 + by + + + Bill Fisher + + + +

+ +
+ +
+

A more up-to-date version of this post is available as part of the Flux documentation.

+ +

Flux is the application architecture that Facebook uses to build web applications with React. It's based on a unidirectional data flow. In previous blog posts and documentation articles, we've shown the basic structure and data flow, more closely examined the dispatcher and action creators, and shown how to put it all together with a tutorial. Now let's look at how to do formal unit testing of Flux applications with Jest, Facebook's auto-mocking testing framework.

+

Testing with Jest #

+

For a unit test to operate on a truly isolated unit of the application, we need to mock every module except the one we are testing. Jest makes the mocking of other parts of a Flux application trivial. To illustrate testing with Jest, we'll return to our example TodoMVC application.

+ +

The first steps toward working with Jest are as follows:

+ +
    +
  1. Get the module dependencies for the application installed by running npm install.
  2. +
  3. Create a directory __tests__/ with a test file, in this case TodoStore-test.js
  4. +
  5. Run npm install jest-cli —save-dev
  6. +
  7. Add the following to your package.json
  8. +
+
{
+  ...
+  "scripts": {
+    "test": "jest"
+  }
+  ...
+}
+
+

Now you're ready to run your tests from the command line with npm test.

+ +

By default, all modules are mocked, so the only boilerplate we need in TodoStore-test.js is a declarative call to Jest's dontMock() method.

+
jest.dontMock('TodoStore');
+
+

This tells Jest to let TodoStore be a real object with real, live methods. Jest will mock all other objects involved with the test.

+

Testing Stores #

+

At Facebook, Flux stores often receive a great deal of formal unit test coverage, as this is where the application state and logic lives. Stores are arguably the most important place in a Flux application to provide coverage, but at first glance, it's not entirely obvious how to test them.

+ +

By design, stores can't be modified from the outside. They have no setters. The only way new data can enter a store is through the callback it registers with the dispatcher.

+ +

We therefore need to simulate the Flux data flow with this one weird trick.

+
var mockRegister = MyDispatcher.register;
+var mockRegisterInfo = mockRegister.mock;
+var callsToRegister = mockRegisterInfo.calls;
+var firstCall = callsToRegister[0];
+var firstArgument = firstCall[0];
+var callback = firstArgument;
+
+

We now have the store's registered callback, the sole mechanism by which data can enter the store.

+ +

For folks new to Jest, or mocks in general, it might not be entirely obvious what is happening in that code block, so let's look at each part of it a bit more closely. We start out by looking at the register() method of our application's dispatcher — the method that the store uses to register its callback with the dispatcher. The dispatcher has been thoroughly mocked automatically by Jest, so we can get a reference to the mocked version of the register() method just as we would normally refer to that method in our production code. But we can get additional information about that method with the mock property of that method. We don't often think of methods having properties, but in Jest, this idea is vital. Every method of a mocked object has this property, and it allows us to examine how the method is being called during the test. A chronologically ordered list of calls to register() is available with the calls property of mock, and each of these calls has a list of the arguments that were used in each method call.

+ +

So in this code, we are really saying, "Give me a reference to the first argument of the first call to MyDispatcher's register() method." That first argument is the store's callback, so now we have all we need to start testing. But first, we can save ourselves some semicolons and roll all of this into a single line:

+
callback = MyDispatcher.register.mock.calls[0][0];
+
+

We can invoke that callback whenever we like, independent of our application's dispatcher or action creators. We will, in fact, fake the behavior of the dispatcher and action creators by invoking the callback with an action that we'll create directly in our test.

+
var payload = {
+  source: 'VIEW_ACTION',
+  action: {
+    actionType: TodoConstants.TODO_CREATE,
+    text: 'foo'
+  }
+};
+callback(payload);
+var all = TodoStore.getAll();
+var keys = Object.keys(all);
+expect(all[keys[0]].text).toEqual('foo');
+

Putting it All Together #

+

The example Flux TodoMVC application has been updated with an example test for the TodoStore, but let's look at an abbreviated version of the entire test. The most important things to notice in this test are how we keep a reference to the store's registered callback in the closure of the test, and how we recreate the store before every test so that we clear the state of the store entirely.

+
jest.dontMock('../TodoStore');
+jest.dontMock('react/lib/merge');
+
+describe('TodoStore', function() {
+
+  var TodoConstants = require('../../constants/TodoConstants');
+
+  // mock actions inside dispatch payloads
+  var actionTodoCreate = {
+    source: 'VIEW_ACTION',
+    action: {
+      actionType: TodoConstants.TODO_CREATE,
+      text: 'foo'
+    }
+  };
+  var actionTodoDestroy = {
+    source: 'VIEW_ACTION',
+    action: {
+      actionType: TodoConstants.TODO_DESTROY,
+      id: 'replace me in test'
+    }
+  };
+
+  var AppDispatcher;
+  var TodoStore;
+  var callback;
+
+  beforeEach(function() {
+    AppDispatcher = require('../../dispatcher/AppDispatcher');
+    TodoStore = require('../TodoStore');
+    callback = AppDispatcher.register.mock.calls[0][0];
+  });
+
+  it('registers a callback with the dispatcher', function() {
+    expect(AppDispatcher.register.mock.calls.length).toBe(1);
+  });
+
+  it('initializes with no to-do items', function() {
+    var all = TodoStore.getAll();
+    expect(all).toEqual({});
+  });
+
+  it('creates a to-do item', function() {
+    callback(actionTodoCreate);
+    var all = TodoStore.getAll();
+    var keys = Object.keys(all);
+    expect(keys.length).toBe(1);
+    expect(all[keys[0]].text).toEqual('foo');
+  });
+
+  it('destroys a to-do item', function() {
+    callback(actionTodoCreate);
+    var all = TodoStore.getAll();
+    var keys = Object.keys(all);
+    expect(keys.length).toBe(1);
+    actionTodoDestroy.action.id = keys[0];
+    callback(actionTodoDestroy);
+    expect(all[keys[0]]).toBeUndefined();
+  });
+
+});
+
+

You can take a look at all this code in the TodoStore's tests on GitHub as well.

+

Mocking Data Derived from Other Stores #

+

Sometimes our stores rely on data from other stores. Because all of our modules are mocked, we'll need to simulate the data that comes from the other store. We can do this by retrieving the mock function and adding a custom return value to it.

+
var MyOtherStore = require('../MyOtherStore');
+MyOtherStore.getState.mockReturnValue({
+  '123': {
+    id: '123',
+    text: 'foo'
+  },
+  '456': {
+    id: '456',
+    text: 'bar'
+  }
+});
+
+

Now we have a collection of objects that will come back from MyOtherStore whenever we call MyOtherStore.getState() in our tests. Any application state can be simulated with a combination of these custom return values and the previously shown technique of working with the store's registered callback.

+ +

A brief example of this technique is up on GitHub within the Flux Chat example's UnreadThreadStore-test.js.

+ +

For more information about the mock property of mocked methods or Jest's ability to provide custom mock values, see Jest's documentation on mock functions.

+

Moving Logic from React to Stores #

+

What often starts as a little piece of seemingly benign logic in our React components often presents a problem while creating unit tests. We want to be able to write tests that read like a specification for our application's behavior, and when application logic slips into our view layer, this becomes more difficult.

+ +

For example, when a user has marked each of their to-do items as complete, the TodoMVC specification dictates that we should also change the status of the "Mark all as complete" checkbox automatically. To create that logic, we might be tempted to write code like this in our MainSection's render() method:

+
var allTodos = this.props.allTodos;
+var allChecked = true;
+for (var id in allTodos) {
+  if (!allTodos[id].complete) {
+    allChecked = false;
+    break;
+  }
+}
+...
+
+return (
+  <section id="main">
+  <input
+    id="toggle-all"
+    type="checkbox"
+    checked={allChecked ? 'checked' : ''}
+  />
+  ...
+  </section>
+);
+
+

While this seems like an easy, normal thing to do, this is an example of application logic slipping into the views, and it can't be described in our spec-style TodoStore test. Let's take that logic and move it to the store. First, we'll create a public method on the store that will encapsulate that logic:

+
areAllComplete: function() {
+  for (var id in _todos) {
+    if (!_todos[id].complete) {
+      return false;
+    }
+  }
+  return true;
+},
+
+

Now we have the application logic where it belongs, and we can write the following test:

+
it('determines whether all to-do items are complete', function() {
+  var i = 0;
+  for (; i < 3; i++) {
+    callback(mockTodoCreate);
+  }
+  expect(TodoStore.areAllComplete()).toBe(false);
+
+  var all = TodoStore.getAll();
+  for (key in all) {
+    callback({
+      source: 'VIEW_ACTION',
+      action: {
+        actionType: TodoConstants.TODO_COMPLETE,
+        id: key
+      }
+    });
+  }
+  expect(TodoStore.areAllComplete()).toBe(true);
+
+  callback({
+    source: 'VIEW_ACTION',
+    action: {
+      actionType: TodoConstants.TODO_UNDO_COMPLETE,
+      id: key
+    }
+  });
+  expect(TodoStore.areAllComplete()).toBe(false);
+});
+
+

Finally, we revise our view layer. We'll call for that data in the controller-view, TodoApp.js, and pass it down to the MainSection component.

+
function getTodoState() {
+  return {
+    allTodos: TodoStore.getAll(),
+    areAllComplete: TodoStore.areAllComplete()
+  };
+}
+
+var TodoApp = React.createClass({
+...
+
+  /**
+   * @return {object}
+   */
+  render: function() {
+    return (
+      ...
+      <MainSection
+        allTodos={this.state.allTodos}
+        areAllComplete={this.state.areAllComplete}
+      />
+      ...
+    );
+  },
+
+  /**
+   * Event handler for 'change' events coming from the TodoStore
+   */
+  _onChange: function() {
+    this.setState(getTodoState());
+  }
+
+});
+
+

And then we'll utilize that property for the rendering of the checkbox.

+
render: function() {
+  ...
+
+  return (
+    <section id="main">
+    <input
+      id="toggle-all"
+      type="checkbox"
+      checked={this.props.areAllComplete ? 'checked' : ''}
+    />
+    ...
+    </section>
+  );
+},
+
+

To learn how to test React components themselves, check out the Jest tutorial for React and the ReactTestUtils documentation.

+

Further Reading #

+ + +
+ + + +
+ +
+ +

React v0.11.2 @@ -425,61 +720,6 @@ This is not the intended way to use React but can be useful as last resort if yo -

- -
- - -

- - Flux: Actions and the Dispatcher - -

- -

- July 30, 2014 - by - - - Bill Fisher - - - -

- -
- -
-

Flux is the application architecture Facebook uses to build JavaScript applications. It's based on a unidirectional data flow. We've built everything from small widgets to huge applications with Flux, and it's handled everything we've thrown at it. Because we've found it to be a great way to structure our code, we're excited to share it with the open source community. Jing Chen presented Flux at the F8 conference, and since that time we've seen a lot of interest in it. We've also published an overview of Flux and a TodoMVC example, with an accompanying tutorial.

- -

Flux is more of a pattern than a full-blown framework, and you can start using it without a lot of new code beyond React. Up until recently, however, we haven't released one crucial piece of our Flux software: the dispatcher. But along with the creation of the new Flux code repository and Flux website, we've now open sourced the same dispatcher we use in our production applications.

-

Where the Dispatcher Fits in the Flux Data Flow #

-

The dispatcher is a singleton, and operates as the central hub of data flow in a Flux application. It is essentially a registry of callbacks, and can invoke these callbacks in order. Each store registers a callback with the dispatcher. When new data comes into the dispatcher, it then uses these callbacks to propagate that data to all of the stores. The process of invoking the callbacks is initiated through the dispatch() method, which takes a data payload object as its sole argument.

-

Actions and ActionCreators #

-

When new data enters the system, whether through a person interacting with the application or through a web api call, that data is packaged into an action — an object literal containing the new fields of data and a specific action type. We often create a library of helper methods called ActionCreators that not only create the action object, but also pass the action to the dispatcher.

- -

Different actions are identified by a type attribute. When all of the stores receive the action, they typically use this attribute to determine if and how they should respond to it. In a Flux application, both stores and views control themselves; they are not acted upon by external objects. Actions flow into the stores through the callbacks they define and register, not through setter methods.

- -

Letting the stores update themselves eliminates many entanglements typically found in MVC applications, where cascading updates between models can lead to unstable state and make accurate testing very difficult. The objects within a Flux application are highly decoupled, and adhere very strongly to the Law of Demeter, the principle that each object within a system should know as little as possible about the other objects in the system. This results in software that is more maintainable, adaptable, testable, and easier for new engineering team members to understand.

- -

-

Why We Need a Dispatcher #

-

As an application grows, dependencies across different stores are a near certainty. Store A will inevitably need Store B to update itself first, so that Store A can know how to update itself. We need the dispatcher to be able to invoke the callback for Store B, and finish that callback, before moving forward with Store A. To declaratively assert this dependency, a store needs to be able to say to the dispatcher, "I need to wait for Store B to finish processing this action." The dispatcher provides this functionality through its waitFor() method.

- -

The dispatch() method provides a simple, synchronous iteration through the callbacks, invoking each in turn. When waitFor() is encountered within one of the callbacks, execution of that callback stops and waitFor() provides us with a new iteration cycle over the dependencies. After the entire set of dependencies have been fulfilled, the original callback then continues to execute.

- -

Further, the waitFor() method may be used in different ways for different actions, within the same store's callback. In one case, Store A might need to wait for Store B. But in another case, it might need to wait for Store C. Using waitFor() within the code block that is specific to an action allows us to have fine-grained control of these dependencies.

- -

Problems arise, however, if we have circular dependencies. That is, if Store A needs to wait for Store B, and Store B needs to wait for Store A, we could wind up in an endless loop. The dispatcher now available in the Flux repo protects against this by throwing an informative error to alert the developer that this problem has occurred. The developer can then create a third store and resolve the circular dependency.

-

Example Chat App #

-

Along with the same dispatcher that Facebook uses in its production applications, we've also published a new example chat app, slightly more complicated than the simplistic TodoMVC, so that engineers can better understand how Flux solves problems like dependencies between stores and calls to a web API.

- -

We're hopeful that the new Flux repository will grow with time to include additional tools, boilerplate code and further examples. And we hope that Flux will prove as useful to you as it has to us. Enjoy!

- -
- - -
diff --git a/blog/page11/index.html b/blog/page11/index.html index 16106ce021..d439a10aa3 100644 --- a/blog/page11/index.html +++ b/blog/page11/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,61 @@
+

+ + Flux: Actions and the Dispatcher + +

+ +

+ July 30, 2014 + by + + + Bill Fisher + + + +

+ +
+ +
+

Flux is the application architecture Facebook uses to build JavaScript applications. It's based on a unidirectional data flow. We've built everything from small widgets to huge applications with Flux, and it's handled everything we've thrown at it. Because we've found it to be a great way to structure our code, we're excited to share it with the open source community. Jing Chen presented Flux at the F8 conference, and since that time we've seen a lot of interest in it. We've also published an overview of Flux and a TodoMVC example, with an accompanying tutorial.

+ +

Flux is more of a pattern than a full-blown framework, and you can start using it without a lot of new code beyond React. Up until recently, however, we haven't released one crucial piece of our Flux software: the dispatcher. But along with the creation of the new Flux code repository and Flux website, we've now open sourced the same dispatcher we use in our production applications.

+

Where the Dispatcher Fits in the Flux Data Flow #

+

The dispatcher is a singleton, and operates as the central hub of data flow in a Flux application. It is essentially a registry of callbacks, and can invoke these callbacks in order. Each store registers a callback with the dispatcher. When new data comes into the dispatcher, it then uses these callbacks to propagate that data to all of the stores. The process of invoking the callbacks is initiated through the dispatch() method, which takes a data payload object as its sole argument.

+

Actions and ActionCreators #

+

When new data enters the system, whether through a person interacting with the application or through a web api call, that data is packaged into an action — an object literal containing the new fields of data and a specific action type. We often create a library of helper methods called ActionCreators that not only create the action object, but also pass the action to the dispatcher.

+ +

Different actions are identified by a type attribute. When all of the stores receive the action, they typically use this attribute to determine if and how they should respond to it. In a Flux application, both stores and views control themselves; they are not acted upon by external objects. Actions flow into the stores through the callbacks they define and register, not through setter methods.

+ +

Letting the stores update themselves eliminates many entanglements typically found in MVC applications, where cascading updates between models can lead to unstable state and make accurate testing very difficult. The objects within a Flux application are highly decoupled, and adhere very strongly to the Law of Demeter, the principle that each object within a system should know as little as possible about the other objects in the system. This results in software that is more maintainable, adaptable, testable, and easier for new engineering team members to understand.

+ +

+

Why We Need a Dispatcher #

+

As an application grows, dependencies across different stores are a near certainty. Store A will inevitably need Store B to update itself first, so that Store A can know how to update itself. We need the dispatcher to be able to invoke the callback for Store B, and finish that callback, before moving forward with Store A. To declaratively assert this dependency, a store needs to be able to say to the dispatcher, "I need to wait for Store B to finish processing this action." The dispatcher provides this functionality through its waitFor() method.

+ +

The dispatch() method provides a simple, synchronous iteration through the callbacks, invoking each in turn. When waitFor() is encountered within one of the callbacks, execution of that callback stops and waitFor() provides us with a new iteration cycle over the dependencies. After the entire set of dependencies have been fulfilled, the original callback then continues to execute.

+ +

Further, the waitFor() method may be used in different ways for different actions, within the same store's callback. In one case, Store A might need to wait for Store B. But in another case, it might need to wait for Store C. Using waitFor() within the code block that is specific to an action allows us to have fine-grained control of these dependencies.

+ +

Problems arise, however, if we have circular dependencies. That is, if Store A needs to wait for Store B, and Store B needs to wait for Store A, we could wind up in an endless loop. The dispatcher now available in the Flux repo protects against this by throwing an informative error to alert the developer that this problem has occurred. The developer can then create a third store and resolve the circular dependency.

+

Example Chat App #

+

Along with the same dispatcher that Facebook uses in its production applications, we've also published a new example chat app, slightly more complicated than the simplistic TodoMVC, so that engineers can better understand how Flux solves problems like dependencies between stores and calls to a web API.

+ +

We're hopeful that the new Flux repository will grow with time to include additional tools, boilerplate code and further examples. And we hope that Flux will prove as useful to you as it has to us. Enjoy!

+ +
+ + + +
+ +
+ +

Community Round-up #20 @@ -595,78 +650,6 @@ Minified build for production: - - -

- - Community Round-up #19 - -

- -

- June 27, 2014 - by - - - Cheng Lou - - - -

- -
- -
-

React Meetups! #

-

Ever wanted to find developers who also share the same interest in React than you? Recently, there has been a React Meetup in San Francisco (courtesy of Telmate), and one in London (courtesy of Stuart Harris, Cain Ullah and Zoe Merchant). These two events have been big successes; a second one in London is already planned.

- -

If you don't live near San Francisco or London, why not start one in your community?

-

Complementary Tools #

-

In case you haven't seen it, we've consolidated the tooling solution around React on this wiki page. Some of the notable recent entries include:

- - - -

These are some of the links that often pop up on the #reactjs IRC channel. If you made something that you think deserves to be shown on the wiki, feel free to add it!

-

React in Interesting Places #

-

The core concepts React themselves is something very valuable that the community is exploring and pushing further. A year ago, we wouldn't have imagined something like Bruce Hauman's Flappy Bird ClojureScript port, whose interactive programming has been made possible through React:

- - - -

And don't forget Pete Hunt's Wolfenstein 3D rendering engine in React (source code). While it's nearly a year old, it's still a nice demo.

- -

- -

Give us a shoutout on IRC or React Google Groups if you've used React in some Interesting places.

-

Even More People Using React #

Prismatic #

-

Prismatic recently shrank their codebase fivefold with the help of React and its popular ClojureScript wrapper, Om. They detailed their very positive experience here.

- -
-

Finally, the state is normalized: each piece of information is represented in a single place. Since React ensures consistency between the DOM and the application data, the programmer can focus on ensuring that the state properly stays up to date in response to user input. If the application state is normalized, then this consistency is guaranteed by definition, completely avoiding the possibility of an entire class of common bugs.

-
-

Adobe Brackets #

-

Kevin Dangoor works on Brackets, the open-source code editor. After writing his first impression on React, he followed up with another insightful article on how to gradually make the code transition, how to preserve the editor's good parts, and how to tune Brackets' tooling around JSX.

- -
-

We don’t need to switch to React everywhere, all at once. It’s not a framework that imposes anything on the application structure. [...] Easy, iterative adoption is definitely something in React’s favor for us.

-
-

Storehouse #

-

Storehouse (Apple Design Award 2014)'s web presence is build with React. Here's an example story. Congratulations on the award!

-

Vim Awesome #

-

Vim Awesome, an open-source Vim plugins directory built on React, was just launched. Be sure to check out the source code if you're curious to see an example of how to build a small single-page React app.

-

Random Tweets #

- - -
- - -

diff --git a/blog/page12/index.html b/blog/page12/index.html index c266205b49..934c997d3c 100644 --- a/blog/page12/index.html +++ b/blog/page12/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,78 @@
+

+ + Community Round-up #19 + +

+ +

+ June 27, 2014 + by + + + Cheng Lou + + + +

+ +
+ +
+

React Meetups! #

+

Ever wanted to find developers who also share the same interest in React than you? Recently, there has been a React Meetup in San Francisco (courtesy of Telmate), and one in London (courtesy of Stuart Harris, Cain Ullah and Zoe Merchant). These two events have been big successes; a second one in London is already planned.

+ +

If you don't live near San Francisco or London, why not start one in your community?

+

Complementary Tools #

+

In case you haven't seen it, we've consolidated the tooling solution around React on this wiki page. Some of the notable recent entries include:

+ + + +

These are some of the links that often pop up on the #reactjs IRC channel. If you made something that you think deserves to be shown on the wiki, feel free to add it!

+

React in Interesting Places #

+

The core concepts React themselves is something very valuable that the community is exploring and pushing further. A year ago, we wouldn't have imagined something like Bruce Hauman's Flappy Bird ClojureScript port, whose interactive programming has been made possible through React:

+ + + +

And don't forget Pete Hunt's Wolfenstein 3D rendering engine in React (source code). While it's nearly a year old, it's still a nice demo.

+ +

+ +

Give us a shoutout on IRC or React Google Groups if you've used React in some Interesting places.

+

Even More People Using React #

Prismatic #

+

Prismatic recently shrank their codebase fivefold with the help of React and its popular ClojureScript wrapper, Om. They detailed their very positive experience here.

+ +
+

Finally, the state is normalized: each piece of information is represented in a single place. Since React ensures consistency between the DOM and the application data, the programmer can focus on ensuring that the state properly stays up to date in response to user input. If the application state is normalized, then this consistency is guaranteed by definition, completely avoiding the possibility of an entire class of common bugs.

+
+

Adobe Brackets #

+

Kevin Dangoor works on Brackets, the open-source code editor. After writing his first impression on React, he followed up with another insightful article on how to gradually make the code transition, how to preserve the editor's good parts, and how to tune Brackets' tooling around JSX.

+ +
+

We don’t need to switch to React everywhere, all at once. It’s not a framework that imposes anything on the application structure. [...] Easy, iterative adoption is definitely something in React’s favor for us.

+
+

Storehouse #

+

Storehouse (Apple Design Award 2014)'s web presence is build with React. Here's an example story. Congratulations on the award!

+

Vim Awesome #

+

Vim Awesome, an open-source Vim plugins directory built on React, was just launched. Be sure to check out the source code if you're curious to see an example of how to build a small single-page React app.

+

Random Tweets #

+ + +
+ + + +
+ +
+ +

One Year of Open-Source React @@ -297,101 +369,6 @@ report bugs on GitHub.

-

- -
- - -

- - React v0.10 - -

- -

- March 21, 2014 - by - - - Paul O’Shannessy - - - -

- -
- -
-

Hot on the heels of the release candidate earlier this week, we're ready to call v0.10 done. The only major issue we discovered had to do with the react-tools package, which has been updated. We've copied over the changelog from the RC with some small clarifying changes.

- -

The release is available for download from the CDN:

- - - -

We've also published version 0.10.0 of the react and react-tools packages on npm and the react package on bower.

- -

Please try these builds out and file an issue on GitHub if you see anything awry.

-

Clone On Mount #

-

The main purpose of this release is to provide a smooth upgrade path as we evolve some of the implementation of core. In v0.9 we started warning in cases where you called methods on unmounted components. This is part of an effort to enforce the idea that the return value of a component (React.DOM.div(), MyComponent()) is in fact not a reference to the component instance React uses in the virtual DOM. The return value is instead a light-weight object that React knows how to use. Since the return value currently is a reference to the same object React uses internally, we need to make this transition in stages as many people have come to depend on this implementation detail.

- -

In 0.10, we’re adding more warnings to catch a similar set of patterns. When a component is mounted we clone it and use that object for our internal representation. This allows us to capture calls you think you’re making to a mounted component. We’ll forward them on to the right object, but also warn you that this is breaking. See “Access to the Mounted Instance” on this page. Most of the time you can solve your pattern by using refs.

- -

Storing a reference to your top level component is a pattern touched upon on that page, but another examples that demonstrates what we see a lot of:

-
// This is a common pattern. However instance here really refers to a
-// "descriptor", not necessarily the mounted instance.
-var instance = <MyComponent/>;
-React.renderComponent(instance);
-// ...
-instance.setProps(...);
-
-// The change here is very simple. The return value of renderComponent will be
-// the mounted instance.
-var instance = React.renderComponent(<MyComponent/>)
-// ...
-instance.setProps(...);
-
-

These warnings and method forwarding are only enabled in the development build. The production builds continue to work as they did in v0.9. We strongly encourage you to use the development builds to catch these warnings and fix the call sites.

- -

The plan for v0.11 is that we will go fully to "descriptors". Method calls on the return value of MyComponent() will fail hard.

-

Changelog #

React Core #

New Features #

-
    -
  • Added warnings to help migrate towards descriptors
  • -
  • Made it possible to server render without React-related markup (data-reactid, data-react-checksum). This DOM will not be mountable by React. Read the docs for React.renderComponentToStaticMarkup
  • -
  • Added support for more attributes: - -
      -
    • srcSet for <img> to specify images at different pixel ratios
    • -
    • textAnchor for SVG
    • -
  • -
-

Bug Fixes #

-
    -
  • Ensure all void elements don’t insert a closing tag into the markup.
  • -
  • Ensure className={false} behaves consistently
  • -
  • Ensure this.refs is defined, even if no refs are specified.
  • -
-

Addons #

- -

react-tools #

-
    -
  • Added an option argument to transform function. The only option supported is harmony, which behaves the same as jsx --harmony on the command line. This uses the ES6 transforms from jstransform.
  • -
- -
- - -
diff --git a/blog/page13/index.html b/blog/page13/index.html index 016286a5ee..549dd69d0c 100644 --- a/blog/page13/index.html +++ b/blog/page13/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,101 @@
+

+ + React v0.10 + +

+ +

+ March 21, 2014 + by + + + Paul O’Shannessy + + + +

+ +
+ +
+

Hot on the heels of the release candidate earlier this week, we're ready to call v0.10 done. The only major issue we discovered had to do with the react-tools package, which has been updated. We've copied over the changelog from the RC with some small clarifying changes.

+ +

The release is available for download from the CDN:

+ + + +

We've also published version 0.10.0 of the react and react-tools packages on npm and the react package on bower.

+ +

Please try these builds out and file an issue on GitHub if you see anything awry.

+

Clone On Mount #

+

The main purpose of this release is to provide a smooth upgrade path as we evolve some of the implementation of core. In v0.9 we started warning in cases where you called methods on unmounted components. This is part of an effort to enforce the idea that the return value of a component (React.DOM.div(), MyComponent()) is in fact not a reference to the component instance React uses in the virtual DOM. The return value is instead a light-weight object that React knows how to use. Since the return value currently is a reference to the same object React uses internally, we need to make this transition in stages as many people have come to depend on this implementation detail.

+ +

In 0.10, we’re adding more warnings to catch a similar set of patterns. When a component is mounted we clone it and use that object for our internal representation. This allows us to capture calls you think you’re making to a mounted component. We’ll forward them on to the right object, but also warn you that this is breaking. See “Access to the Mounted Instance” on this page. Most of the time you can solve your pattern by using refs.

+ +

Storing a reference to your top level component is a pattern touched upon on that page, but another examples that demonstrates what we see a lot of:

+
// This is a common pattern. However instance here really refers to a
+// "descriptor", not necessarily the mounted instance.
+var instance = <MyComponent/>;
+React.renderComponent(instance);
+// ...
+instance.setProps(...);
+
+// The change here is very simple. The return value of renderComponent will be
+// the mounted instance.
+var instance = React.renderComponent(<MyComponent/>)
+// ...
+instance.setProps(...);
+
+

These warnings and method forwarding are only enabled in the development build. The production builds continue to work as they did in v0.9. We strongly encourage you to use the development builds to catch these warnings and fix the call sites.

+ +

The plan for v0.11 is that we will go fully to "descriptors". Method calls on the return value of MyComponent() will fail hard.

+

Changelog #

React Core #

New Features #

+
    +
  • Added warnings to help migrate towards descriptors
  • +
  • Made it possible to server render without React-related markup (data-reactid, data-react-checksum). This DOM will not be mountable by React. Read the docs for React.renderComponentToStaticMarkup
  • +
  • Added support for more attributes: + +
      +
    • srcSet for <img> to specify images at different pixel ratios
    • +
    • textAnchor for SVG
    • +
  • +
+

Bug Fixes #

+
    +
  • Ensure all void elements don’t insert a closing tag into the markup.
  • +
  • Ensure className={false} behaves consistently
  • +
  • Ensure this.refs is defined, even if no refs are specified.
  • +
+

Addons #

+ +

react-tools #

+
    +
  • Added an option argument to transform function. The only option supported is harmony, which behaves the same as jsx --harmony on the command line. This uses the ES6 transforms from jstransform.
  • +
+ +
+ + + +
+ +
+ +

React v0.10 RC @@ -523,153 +618,6 @@ Minified build for production: - - -

- - React v0.9 RC - -

- -

- February 16, 2014 - by - - - Ben Alpert - - - -

- -
- -
-

We're almost ready to release React v0.9! We're posting a release candidate so that you can test your apps on it; we'd much prefer to find show-stopping bugs now rather than after we release.

- -

The release candidate is available for download from the CDN:

- - - -

We've also published version 0.9.0-rc1 of the react and react-tools packages on npm and the react package on bower.

- -

Please try these builds out and file an issue on GitHub if you see anything awry.

-

Upgrade Notes #

-

In addition to the changes to React core listed below, we've made a small change to the way JSX interprets whitespace to make things more consistent. With this release, space between two components on the same line will be preserved, while a newline separating a text node from a tag will be eliminated in the output. Consider the code:

-
<div>
-  Monkeys:
-  {listOfMonkeys} {submitButton}
-</div>
-
-

In v0.8 and below, it was transformed to the following:

-
React.DOM.div(null,
-  " Monkeys: ",
-  listOfMonkeys, submitButton
-)
-
-

In v0.9, it will be transformed to this JS instead:

-
React.DOM.div(null,
-  "Monkeys:",
-  listOfMonkeys, " ", submitButton
-)
-
-

We believe this new behavior is more helpful and elimates cases where unwanted whitespace was previously added.

- -

In cases where you want to preserve the space adjacent to a newline, you can write a JS string like {"Monkeys: "} in your JSX source. We've included a script to do an automated codemod of your JSX source tree that preserves the old whitespace behavior by adding and removing spaces appropriately. You can install jsx_whitespace_transformer from npm and run it over your source tree to modify files in place. The transformed JSX files will preserve your code's existing whitespace behavior.

-

Changelog #

React Core #

Breaking Changes #

-
    -
  • The lifecycle methods componentDidMount and componentDidUpdate no longer receive the root node as a parameter; use this.getDOMNode() instead
  • -
  • Whenever a prop is equal to undefined, the default value returned by getDefaultProps will now be used instead
  • -
  • React.unmountAndReleaseReactRootNode was previously deprecated and has now been removed
  • -
  • React.renderComponentToString is now synchronous and returns the generated HTML string
  • -
  • Full-page rendering (that is, rendering the <html> tag using React) is now supported only when starting with server-rendered markup
  • -
  • On mouse wheel events, deltaY is no longer negated
  • -
  • When prop types validation fails, a warning is logged instead of an error thrown (with the production build of React, the type checks are now skipped for performance)
  • -
  • On input, select, and textarea elements, .getValue() is no longer supported; use .getDOMNode().value instead
  • -
  • this.context on components is now reserved for internal use by React
  • -
-

New Features #

-
    -
  • React now never rethrows errors, so stack traces are more accurate and Chrome's purple break-on-error stop sign now works properly
  • -
  • Added a new tool for profiling React components and identifying places where defining shouldComponentUpdate can give performance improvements
  • -
  • Added support for SVG tags defs, linearGradient, polygon, radialGradient, stop
  • -
  • Added support for more attributes: - -
      -
    • noValidate and formNoValidate for forms
    • -
    • property for Open Graph <meta> tags
    • -
    • sandbox, seamless, and srcDoc for <iframe> tags
    • -
    • scope for screen readers
    • -
    • span for <colgroup> tags
    • -
  • -
  • Added support for defining propTypes in mixins
  • -
  • Added any, arrayOf, component, oneOfType, renderable, shape to React.PropTypes
  • -
  • Added support for statics on component spec for static component methods
  • -
  • On all events, .currentTarget is now properly set
  • -
  • On keyboard events, .key is now polyfilled in all browsers for special (non-printable) keys
  • -
  • On clipboard events, .clipboardData is now polyfilled in IE
  • -
  • On drag events, .dataTransfer is now present
  • -
  • Added support for onMouseOver and onMouseOut in addition to the existing onMouseEnter and onMouseLeave events
  • -
  • Added support for onLoad and onError on <img> elements
  • -
  • Added support for onReset on <form> elements
  • -
  • The autoFocus attribute is now polyfilled consistently on input, select, and textarea
  • -
-

Bug Fixes #

-
    -
  • React no longer adds an __owner__ property to each component's props object; passed-in props are now never mutated
  • -
  • When nesting top-level components (e.g., calling React.renderComponent within componentDidMount), events now properly bubble to the parent component
  • -
  • Fixed a case where nesting top-level components would throw an error when updating
  • -
  • Passing an invalid or misspelled propTypes type now throws an error
  • -
  • On mouse enter/leave events, .target, .relatedTarget, and .type are now set properly
  • -
  • On composition events, .data is now properly normalized in IE9 and IE10
  • -
  • CSS property values no longer have px appended for the unitless properties columnCount, flex, flexGrow, flexShrink, lineClamp, order, widows
  • -
  • Fixed a memory leak when unmounting children with a componentWillUnmount handler
  • -
  • Fixed a memory leak when renderComponentToString would store event handlers
  • -
  • Fixed an error that could be thrown when removing form elements during a click handler
  • -
  • key values containing . are now supported
  • -
  • Shortened data-reactid values for performance
  • -
  • Components now always remount when the key property changes
  • -
  • Event handlers are attached to document only when necessary, improving performance in some cases
  • -
  • Events no longer use .returnValue in modern browsers, eliminating a warning in Chrome
  • -
  • scrollLeft and scrollTop are no longer accessed on document.body, eliminating a warning in Chrome
  • -
  • General performance fixes, memory optimizations, improvements to warnings and error messages
  • -
-

React with Addons #

-
    -
  • React.addons.TransitionGroup was renamed to React.addons.CSSTransitionGroup
  • -
  • React.addons.TransitionGroup was added as a more general animation wrapper
  • -
  • React.addons.cloneWithProps was added for cloning components and modifying their props
  • -
  • Bug fix for adding back nodes during an exit transition for CSSTransitionGroup
  • -
  • Bug fix for changing transitionLeave in CSSTransitionGroup
  • -
  • Performance optimizations for CSSTransitionGroup
  • -
  • On checkbox <input> elements, checkedLink is now supported for two-way binding
  • -
-

JSX Compiler and react-tools Package #

-
    -
  • Whitespace normalization has changed; now space between two tags on the same line will be preserved, while newlines between two tags will be removed
  • -
  • The react-tools npm package no longer includes the React core libraries; use the react package instead.
  • -
  • displayName is now added in more cases, improving error messages and names in the React Dev Tools
  • -
  • Fixed an issue where an invalid token error was thrown after a JSX closing tag
  • -
  • JSXTransformer now uses source maps automatically in modern browsers
  • -
  • JSXTransformer error messages now include the filename and problematic line contents when a file fails to parse
  • -
- -
- - -

diff --git a/blog/page14/index.html b/blog/page14/index.html index 5f6df4b0d6..6a6474d1eb 100644 --- a/blog/page14/index.html +++ b/blog/page14/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,153 @@
+

+ + React v0.9 RC + +

+ +

+ February 16, 2014 + by + + + Ben Alpert + + + +

+ +
+ +
+

We're almost ready to release React v0.9! We're posting a release candidate so that you can test your apps on it; we'd much prefer to find show-stopping bugs now rather than after we release.

+ +

The release candidate is available for download from the CDN:

+ + + +

We've also published version 0.9.0-rc1 of the react and react-tools packages on npm and the react package on bower.

+ +

Please try these builds out and file an issue on GitHub if you see anything awry.

+

Upgrade Notes #

+

In addition to the changes to React core listed below, we've made a small change to the way JSX interprets whitespace to make things more consistent. With this release, space between two components on the same line will be preserved, while a newline separating a text node from a tag will be eliminated in the output. Consider the code:

+
<div>
+  Monkeys:
+  {listOfMonkeys} {submitButton}
+</div>
+
+

In v0.8 and below, it was transformed to the following:

+
React.DOM.div(null,
+  " Monkeys: ",
+  listOfMonkeys, submitButton
+)
+
+

In v0.9, it will be transformed to this JS instead:

+
React.DOM.div(null,
+  "Monkeys:",
+  listOfMonkeys, " ", submitButton
+)
+
+

We believe this new behavior is more helpful and elimates cases where unwanted whitespace was previously added.

+ +

In cases where you want to preserve the space adjacent to a newline, you can write a JS string like {"Monkeys: "} in your JSX source. We've included a script to do an automated codemod of your JSX source tree that preserves the old whitespace behavior by adding and removing spaces appropriately. You can install jsx_whitespace_transformer from npm and run it over your source tree to modify files in place. The transformed JSX files will preserve your code's existing whitespace behavior.

+

Changelog #

React Core #

Breaking Changes #

+
    +
  • The lifecycle methods componentDidMount and componentDidUpdate no longer receive the root node as a parameter; use this.getDOMNode() instead
  • +
  • Whenever a prop is equal to undefined, the default value returned by getDefaultProps will now be used instead
  • +
  • React.unmountAndReleaseReactRootNode was previously deprecated and has now been removed
  • +
  • React.renderComponentToString is now synchronous and returns the generated HTML string
  • +
  • Full-page rendering (that is, rendering the <html> tag using React) is now supported only when starting with server-rendered markup
  • +
  • On mouse wheel events, deltaY is no longer negated
  • +
  • When prop types validation fails, a warning is logged instead of an error thrown (with the production build of React, the type checks are now skipped for performance)
  • +
  • On input, select, and textarea elements, .getValue() is no longer supported; use .getDOMNode().value instead
  • +
  • this.context on components is now reserved for internal use by React
  • +
+

New Features #

+
    +
  • React now never rethrows errors, so stack traces are more accurate and Chrome's purple break-on-error stop sign now works properly
  • +
  • Added a new tool for profiling React components and identifying places where defining shouldComponentUpdate can give performance improvements
  • +
  • Added support for SVG tags defs, linearGradient, polygon, radialGradient, stop
  • +
  • Added support for more attributes: + +
      +
    • noValidate and formNoValidate for forms
    • +
    • property for Open Graph <meta> tags
    • +
    • sandbox, seamless, and srcDoc for <iframe> tags
    • +
    • scope for screen readers
    • +
    • span for <colgroup> tags
    • +
  • +
  • Added support for defining propTypes in mixins
  • +
  • Added any, arrayOf, component, oneOfType, renderable, shape to React.PropTypes
  • +
  • Added support for statics on component spec for static component methods
  • +
  • On all events, .currentTarget is now properly set
  • +
  • On keyboard events, .key is now polyfilled in all browsers for special (non-printable) keys
  • +
  • On clipboard events, .clipboardData is now polyfilled in IE
  • +
  • On drag events, .dataTransfer is now present
  • +
  • Added support for onMouseOver and onMouseOut in addition to the existing onMouseEnter and onMouseLeave events
  • +
  • Added support for onLoad and onError on <img> elements
  • +
  • Added support for onReset on <form> elements
  • +
  • The autoFocus attribute is now polyfilled consistently on input, select, and textarea
  • +
+

Bug Fixes #

+
    +
  • React no longer adds an __owner__ property to each component's props object; passed-in props are now never mutated
  • +
  • When nesting top-level components (e.g., calling React.renderComponent within componentDidMount), events now properly bubble to the parent component
  • +
  • Fixed a case where nesting top-level components would throw an error when updating
  • +
  • Passing an invalid or misspelled propTypes type now throws an error
  • +
  • On mouse enter/leave events, .target, .relatedTarget, and .type are now set properly
  • +
  • On composition events, .data is now properly normalized in IE9 and IE10
  • +
  • CSS property values no longer have px appended for the unitless properties columnCount, flex, flexGrow, flexShrink, lineClamp, order, widows
  • +
  • Fixed a memory leak when unmounting children with a componentWillUnmount handler
  • +
  • Fixed a memory leak when renderComponentToString would store event handlers
  • +
  • Fixed an error that could be thrown when removing form elements during a click handler
  • +
  • key values containing . are now supported
  • +
  • Shortened data-reactid values for performance
  • +
  • Components now always remount when the key property changes
  • +
  • Event handlers are attached to document only when necessary, improving performance in some cases
  • +
  • Events no longer use .returnValue in modern browsers, eliminating a warning in Chrome
  • +
  • scrollLeft and scrollTop are no longer accessed on document.body, eliminating a warning in Chrome
  • +
  • General performance fixes, memory optimizations, improvements to warnings and error messages
  • +
+

React with Addons #

+
    +
  • React.addons.TransitionGroup was renamed to React.addons.CSSTransitionGroup
  • +
  • React.addons.TransitionGroup was added as a more general animation wrapper
  • +
  • React.addons.cloneWithProps was added for cloning components and modifying their props
  • +
  • Bug fix for adding back nodes during an exit transition for CSSTransitionGroup
  • +
  • Bug fix for changing transitionLeave in CSSTransitionGroup
  • +
  • Performance optimizations for CSSTransitionGroup
  • +
  • On checkbox <input> elements, checkedLink is now supported for two-way binding
  • +
+

JSX Compiler and react-tools Package #

+
    +
  • Whitespace normalization has changed; now space between two tags on the same line will be preserved, while newlines between two tags will be removed
  • +
  • The react-tools npm package no longer includes the React core libraries; use the react package instead.
  • +
  • displayName is now added in more cases, improving error messages and names in the React Dev Tools
  • +
  • Fixed an issue where an invalid token error was thrown after a JSX closing tag
  • +
  • JSXTransformer now uses source maps automatically in modern browsers
  • +
  • JSXTransformer error messages now include the filename and problematic line contents when a file fails to parse
  • +
+ +
+ + + +
+ +
+ +

Community Round-up #16 @@ -450,124 +597,6 @@ rails s -

- -
- - -

- - Community Round-up #13 - -

- -

- December 30, 2013 - by - - - Vjeux - - - -

- -
- -
-

Happy holidays! This blog post is a little-late Christmas present for all the React users. Hopefully it will inspire you to write awesome web apps in 2014!

-

React Touch #

-

Pete Hunt wrote three demos showing that React can be used to run 60fps native-like experiences on mobile web. A frosted glass effect, an image gallery with 3d animations and an infinite scroll view.

- -
- -

Try out the demos!

-

Introduction to React #

-

Stoyan Stefanov talked at Joe Dev On Tech about React. He goes over all the features of the library and ends with a concrete example.

- -
-

JSX: E4X The Good Parts #

-

JSX is often compared to the now defunct E4X, Vjeux went over all the E4X features and explained how JSX is different and hopefully doesn't repeat the same mistakes.

- -
-

E4X (ECMAScript for XML) is a Javascript syntax extension and a runtime to manipulate XML. It was promoted by Mozilla but failed to become mainstream and is now deprecated. JSX was inspired by E4X. In this article, I'm going to go over all the features of E4X and explain the design decisions behind JSX.

- -

Historical Context

- -

E4X has been created in 2002 by John Schneider. This was the golden age of XML where it was being used for everything: data, configuration files, code, interfaces (DOM) ... E4X was first implemented inside of Rhino, a Javascript implementation from Mozilla written in Java.

- -

Continue reading ...

-
-

React + Socket.io #

-

Geert Pasteels made a small experiment with Socket.io. He wrote a very small mixin that synchronizes React state with the server. Just include this mixin to your React component and it is now live!

-
changeHandler: function (data) {
-  if (!_.isEqual(data.state, this.state) && this.path === data.path) {
-    this.setState(data.state);
-  }
-},
-componentDidMount: function (root) {
-  this.path = utils.nodePath(root);
-  socket.on('component-change', this.changeHandler);
-},
-componentWillUpdate: function (props, state) {
-  socket.emit('component-change', { path: this.path, state: state });
-},
-componentWillUnmount: function () {
-  socket.removeListener('component-change', this.change);
-}
-
-

Check it out on GitHub...

-

cssobjectify #

-

Andrey Popp implemented a source transform that takes a CSS file and converts it to JSON. This integrates pretty nicely with React.

-
/* style.css */
-MyComponent {
-  font-size: 12px;
-  background-color: red;
-}
-
-/* myapp.js */
-var React = require('react-tools/build/modules/React');
-var Styles = require('./styles.css');
-
-var MyComponent = React.createClass({
-  render: function() {
-    return (
-      <div style={Styles.MyComponent}>
-        Hello, world!
-      </div>
-    )
-  }
-});
-
-

Check it out on GitHub...

-

ngReact #

-

David Chang working at HasOffer wanted to speed up his Angular app and replaced Angular primitives by React at different layers. When using React naively it is 67% faster, but when combining it with angular's transclusion it is 450% slower.

- -
-

Rendering this takes 803ms for 10 iterations, hovering around 35 and 55ms for each data reload (that's 67% faster). You'll notice that the first load takes a little longer than successive loads, and the second load REALLY struggles - here, it's 433ms, which is more than half of the total time! -

- -

Read the full article...

-
-

vim-jsx #

-

Max Wang made a vim syntax highlighting and indentation plugin for vim.

- -
-

Syntax highlighting and indenting for JSX. JSX is a JavaScript syntax transformer which translates inline XML document fragments into JavaScript objects. It was developed by Facebook alongside React.

- -

This bundle requires pangloss's vim-javascript syntax highlighting.

- -

Vim support for inline XML in JS is remarkably similar to the same for PHP.

- -

View on GitHub...

-
-

Random Tweet #

-

- -
- - -
diff --git a/blog/page15/index.html b/blog/page15/index.html index 61023ce930..5da2e7a75e 100644 --- a/blog/page15/index.html +++ b/blog/page15/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,124 @@
+

+ + Community Round-up #13 + +

+ +

+ December 30, 2013 + by + + + Vjeux + + + +

+ +
+ +
+

Happy holidays! This blog post is a little-late Christmas present for all the React users. Hopefully it will inspire you to write awesome web apps in 2014!

+

React Touch #

+

Pete Hunt wrote three demos showing that React can be used to run 60fps native-like experiences on mobile web. A frosted glass effect, an image gallery with 3d animations and an infinite scroll view.

+ +
+ +

Try out the demos!

+

Introduction to React #

+

Stoyan Stefanov talked at Joe Dev On Tech about React. He goes over all the features of the library and ends with a concrete example.

+ +
+

JSX: E4X The Good Parts #

+

JSX is often compared to the now defunct E4X, Vjeux went over all the E4X features and explained how JSX is different and hopefully doesn't repeat the same mistakes.

+ +
+

E4X (ECMAScript for XML) is a Javascript syntax extension and a runtime to manipulate XML. It was promoted by Mozilla but failed to become mainstream and is now deprecated. JSX was inspired by E4X. In this article, I'm going to go over all the features of E4X and explain the design decisions behind JSX.

+ +

Historical Context

+ +

E4X has been created in 2002 by John Schneider. This was the golden age of XML where it was being used for everything: data, configuration files, code, interfaces (DOM) ... E4X was first implemented inside of Rhino, a Javascript implementation from Mozilla written in Java.

+ +

Continue reading ...

+
+

React + Socket.io #

+

Geert Pasteels made a small experiment with Socket.io. He wrote a very small mixin that synchronizes React state with the server. Just include this mixin to your React component and it is now live!

+
changeHandler: function (data) {
+  if (!_.isEqual(data.state, this.state) && this.path === data.path) {
+    this.setState(data.state);
+  }
+},
+componentDidMount: function (root) {
+  this.path = utils.nodePath(root);
+  socket.on('component-change', this.changeHandler);
+},
+componentWillUpdate: function (props, state) {
+  socket.emit('component-change', { path: this.path, state: state });
+},
+componentWillUnmount: function () {
+  socket.removeListener('component-change', this.change);
+}
+
+

Check it out on GitHub...

+

cssobjectify #

+

Andrey Popp implemented a source transform that takes a CSS file and converts it to JSON. This integrates pretty nicely with React.

+
/* style.css */
+MyComponent {
+  font-size: 12px;
+  background-color: red;
+}
+
+/* myapp.js */
+var React = require('react-tools/build/modules/React');
+var Styles = require('./styles.css');
+
+var MyComponent = React.createClass({
+  render: function() {
+    return (
+      <div style={Styles.MyComponent}>
+        Hello, world!
+      </div>
+    )
+  }
+});
+
+

Check it out on GitHub...

+

ngReact #

+

David Chang working at HasOffer wanted to speed up his Angular app and replaced Angular primitives by React at different layers. When using React naively it is 67% faster, but when combining it with angular's transclusion it is 450% slower.

+ +
+

Rendering this takes 803ms for 10 iterations, hovering around 35 and 55ms for each data reload (that's 67% faster). You'll notice that the first load takes a little longer than successive loads, and the second load REALLY struggles - here, it's 433ms, which is more than half of the total time! +

+ +

Read the full article...

+
+

vim-jsx #

+

Max Wang made a vim syntax highlighting and indentation plugin for vim.

+ +
+

Syntax highlighting and indenting for JSX. JSX is a JavaScript syntax transformer which translates inline XML document fragments into JavaScript objects. It was developed by Facebook alongside React.

+ +

This bundle requires pangloss's vim-javascript syntax highlighting.

+ +

Vim support for inline XML in JS is remarkably similar to the same for PHP.

+ +

View on GitHub...

+
+

Random Tweet #

+

+ +
+ + + +
+ +
+ +

Community Round-up #12 @@ -404,144 +522,6 @@ Is this some sort of template language? Specifically no. This might have been th -

- -
- - -

- - Community Round-up #10 - -

- -

- November 6, 2013 - by - - - Vjeux - - - -

- -
- -
-

This is the 10th round-up already and React has come quite far since it was open sourced. Almost all new web projects at Khan Academy, Facebook, and Instagram are being developed using React. React has been deployed in a variety of contexts: a Chrome extension, a Windows 8 application, mobile websites, and desktop websites supporting Internet Explorer 8! Language-wise, React is not only being used within JavaScript but also CoffeeScript and ClojureScript.

- -

The best part is that no drastic changes have been required to support all those use cases. Most of the efforts were targeted at polishing edge cases, performance improvements, and documentation.

-

Khan Academy - Officially moving to React #

-

Joel Burget announced at Hack Reactor that new front-end code at Khan Academy should be written in React!

- -
-

How did we get the rest of the team to adopt React? Using interns as an attack vector! Most full-time devs had already been working on their existing projects for a while and weren't looking to try something new at the time, but our class of summer interns was just arriving. For whatever reason, a lot of them decided to try React for their projects. Then mentors became exposed through code reviews or otherwise touching the new code. In this way React knowledge diffused to almost the whole team over the summer.

- -

Since the first React checkin on June 5, we've somehow managed to accumulate 23500 lines of jsx (React-flavored js) code. Which is terrifying in a way - that's a lot of code - but also really exciting that it was picked up so quickly.

- -

We held three meetings about how we should proceed with React. At the first two we decided to continue experimenting with React and deferred a final decision on whether to adopt it. At the third we adopted the policy that new code should be written in React.

- -

I'm excited that we were able to start nudging code quality forward. However, we still have a lot of work to do! One of the selling points of this transition is adopting a uniform frontend style. We're trying to upgrade all the code from (really old) pure jQuery and (regular old) Backbone views / Handlebars to shiny React. At the moment all we've done is introduce more fragmentation. We won't be gratuitously updating working code (if it ain't broke, don't fix it), but are seeking out parts of the codebase where we can shoot two birds with one stone by rewriting in React while fixing bugs or adding functionality.

- -

Read the full article

-
-

React: Rethinking best practices #

-

Pete Hunt's talk at JSConf EU 2013 is now available in video.

- -
-

Server-side React with PHP #

-

Stoyan Stefanov's series of articles on React has two new entries on how to execute React on the server to generate the initial page load.

- -
-

This post is an initial hack to have React components render server-side in PHP.

- -
    -
  • Problem: Build web UIs
  • -
  • Solution: React
  • -
  • Problem: UI built in JS is anti-SEO (assuming search engines are still noscript) and bad for perceived performance (blank page till JS arrives)
  • -
  • Solution: React page to render the first view
  • -
  • Problem: Can't host node.js apps / I have tons of PHP code
  • -
  • Solution: Use PHP then!
  • -
- -

Read part 1 ...

- -

Read part 2 ...

- -

Rendered markup on the server: -

-
-

TodoMVC Benchmarks #

-

Webkit has a TodoMVC Benchmark that compares different frameworks. They recently included React and here are the results (average of 10 runs in Chrome 30):

- -
    -
  • AngularJS: 4043ms
  • -
  • AngularJSPerf: 3227ms
  • -
  • BackboneJS: 1874ms
  • -
  • EmberJS: 6822ms
  • -
  • jQuery: 14628ms
  • -
  • React: 2864ms
  • -
  • VanillaJS: 5567ms
  • -
- -

Try it yourself!

- -

Please don't take those numbers too seriously, they only reflect one very specific use case and are testing code that wasn't written with performance in mind.

- -

Even though React scores as one of the fastest frameworks in the benchmark, the React code is simple and idiomatic. The only performance tweak used is the following function:

-
/**
- * This is a completely optional performance enhancement that you can implement
- * on any React component. If you were to delete this method the app would still
- * work correctly (and still be very performant!), we just use it as an example
- * of how little code it takes to get an order of magnitude performance improvement.
- */
-shouldComponentUpdate: function (nextProps, nextState) {
-  return (
-    nextProps.todo.id !== this.props.todo.id ||
-    nextProps.todo !== this.props.todo ||
-    nextProps.editing !== this.props.editing ||
-    nextState.editText !== this.state.editText
-  );
-},
-
-

By default, React "re-renders" all the components when anything changes. This is usually fast enough that you don't need to care. However, you can provide a function that can tell whether there will be any change based on the previous and next states and props. If it is faster than re-rendering the component, then you get a performance improvement.

- -

The fact that you can control when components are rendered is a very important characteristic of React as it gives you control over its performance. We are going to talk more about performance in the future, stay tuned.

-

Guess the filter #

-

Connor McSheffrey implemented a small game using React. The goal is to guess which filter has been used to create the Instagram photo. -

-

React vs FruitMachine #

-

Andrew Betts, director of the Financial Times Labs, posted an article comparing FruitMachine and React.

- -
-

Eerily similar, no? Maybe Facebook was inspired by Fruit Machine (after all, we got there first), but more likely, it just shows that this is a pretty decent way to solve the problem, and great minds think alike. We're graduating to a third phase in the evolution of web best practice - from intermingling of markup, style and behaviour, through a phase in which those concerns became ever more separated and encapsulated, and finally to a model where we can do that separation at a component level. Developments like Web Components show the direction the web community is moving, and frameworks like React and Fruit Machine are in fact not a lot more than polyfills for that promised behaviour to come.

- -

Read the full article...

-
- -

Even though we weren't inspired by FruitMachine (React has been used in production since before FruitMachine was open sourced), it's great to see similar technologies emerging and becoming popular.

-

React Brunch #

-

Matthew McCray implemented react-brunch, a JSX compilation step for Brunch.

- -
-

Adds React support to brunch by automatically compiling *.jsx files.

- -

You can configure react-brunch to automatically insert a react header (/** @jsx React.DOM */) into all *.jsx files. Disabled by default.

- -

Install the plugin via npm with npm install --save react-brunch.

- -

Read more...

-
-

Random Tweet #

-

I'm going to start adding a tweet at the end of each round-up. We'll start with this one:

- - - -
- - -
diff --git a/blog/page16/index.html b/blog/page16/index.html index 4ec9114495..a5cc92d6a9 100644 --- a/blog/page16/index.html +++ b/blog/page16/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,144 @@
+

+ + Community Round-up #10 + +

+ +

+ November 6, 2013 + by + + + Vjeux + + + +

+ +
+ +
+

This is the 10th round-up already and React has come quite far since it was open sourced. Almost all new web projects at Khan Academy, Facebook, and Instagram are being developed using React. React has been deployed in a variety of contexts: a Chrome extension, a Windows 8 application, mobile websites, and desktop websites supporting Internet Explorer 8! Language-wise, React is not only being used within JavaScript but also CoffeeScript and ClojureScript.

+ +

The best part is that no drastic changes have been required to support all those use cases. Most of the efforts were targeted at polishing edge cases, performance improvements, and documentation.

+

Khan Academy - Officially moving to React #

+

Joel Burget announced at Hack Reactor that new front-end code at Khan Academy should be written in React!

+ +
+

How did we get the rest of the team to adopt React? Using interns as an attack vector! Most full-time devs had already been working on their existing projects for a while and weren't looking to try something new at the time, but our class of summer interns was just arriving. For whatever reason, a lot of them decided to try React for their projects. Then mentors became exposed through code reviews or otherwise touching the new code. In this way React knowledge diffused to almost the whole team over the summer.

+ +

Since the first React checkin on June 5, we've somehow managed to accumulate 23500 lines of jsx (React-flavored js) code. Which is terrifying in a way - that's a lot of code - but also really exciting that it was picked up so quickly.

+ +

We held three meetings about how we should proceed with React. At the first two we decided to continue experimenting with React and deferred a final decision on whether to adopt it. At the third we adopted the policy that new code should be written in React.

+ +

I'm excited that we were able to start nudging code quality forward. However, we still have a lot of work to do! One of the selling points of this transition is adopting a uniform frontend style. We're trying to upgrade all the code from (really old) pure jQuery and (regular old) Backbone views / Handlebars to shiny React. At the moment all we've done is introduce more fragmentation. We won't be gratuitously updating working code (if it ain't broke, don't fix it), but are seeking out parts of the codebase where we can shoot two birds with one stone by rewriting in React while fixing bugs or adding functionality.

+ +

Read the full article

+
+

React: Rethinking best practices #

+

Pete Hunt's talk at JSConf EU 2013 is now available in video.

+ +
+

Server-side React with PHP #

+

Stoyan Stefanov's series of articles on React has two new entries on how to execute React on the server to generate the initial page load.

+ +
+

This post is an initial hack to have React components render server-side in PHP.

+ +
    +
  • Problem: Build web UIs
  • +
  • Solution: React
  • +
  • Problem: UI built in JS is anti-SEO (assuming search engines are still noscript) and bad for perceived performance (blank page till JS arrives)
  • +
  • Solution: React page to render the first view
  • +
  • Problem: Can't host node.js apps / I have tons of PHP code
  • +
  • Solution: Use PHP then!
  • +
+ +

Read part 1 ...

+ +

Read part 2 ...

+ +

Rendered markup on the server: +

+
+

TodoMVC Benchmarks #

+

Webkit has a TodoMVC Benchmark that compares different frameworks. They recently included React and here are the results (average of 10 runs in Chrome 30):

+ +
    +
  • AngularJS: 4043ms
  • +
  • AngularJSPerf: 3227ms
  • +
  • BackboneJS: 1874ms
  • +
  • EmberJS: 6822ms
  • +
  • jQuery: 14628ms
  • +
  • React: 2864ms
  • +
  • VanillaJS: 5567ms
  • +
+ +

Try it yourself!

+ +

Please don't take those numbers too seriously, they only reflect one very specific use case and are testing code that wasn't written with performance in mind.

+ +

Even though React scores as one of the fastest frameworks in the benchmark, the React code is simple and idiomatic. The only performance tweak used is the following function:

+
/**
+ * This is a completely optional performance enhancement that you can implement
+ * on any React component. If you were to delete this method the app would still
+ * work correctly (and still be very performant!), we just use it as an example
+ * of how little code it takes to get an order of magnitude performance improvement.
+ */
+shouldComponentUpdate: function (nextProps, nextState) {
+  return (
+    nextProps.todo.id !== this.props.todo.id ||
+    nextProps.todo !== this.props.todo ||
+    nextProps.editing !== this.props.editing ||
+    nextState.editText !== this.state.editText
+  );
+},
+
+

By default, React "re-renders" all the components when anything changes. This is usually fast enough that you don't need to care. However, you can provide a function that can tell whether there will be any change based on the previous and next states and props. If it is faster than re-rendering the component, then you get a performance improvement.

+ +

The fact that you can control when components are rendered is a very important characteristic of React as it gives you control over its performance. We are going to talk more about performance in the future, stay tuned.

+

Guess the filter #

+

Connor McSheffrey implemented a small game using React. The goal is to guess which filter has been used to create the Instagram photo. +

+

React vs FruitMachine #

+

Andrew Betts, director of the Financial Times Labs, posted an article comparing FruitMachine and React.

+ +
+

Eerily similar, no? Maybe Facebook was inspired by Fruit Machine (after all, we got there first), but more likely, it just shows that this is a pretty decent way to solve the problem, and great minds think alike. We're graduating to a third phase in the evolution of web best practice - from intermingling of markup, style and behaviour, through a phase in which those concerns became ever more separated and encapsulated, and finally to a model where we can do that separation at a component level. Developments like Web Components show the direction the web community is moving, and frameworks like React and Fruit Machine are in fact not a lot more than polyfills for that promised behaviour to come.

+ +

Read the full article...

+
+ +

Even though we weren't inspired by FruitMachine (React has been used in production since before FruitMachine was open sourced), it's great to see similar technologies emerging and becoming popular.

+

React Brunch #

+

Matthew McCray implemented react-brunch, a JSX compilation step for Brunch.

+ +
+

Adds React support to brunch by automatically compiling *.jsx files.

+ +

You can configure react-brunch to automatically insert a react header (/** @jsx React.DOM */) into all *.jsx files. Disabled by default.

+ +

Install the plugin via npm with npm install --save react-brunch.

+ +

Read more...

+
+

Random Tweet #

+

I'm going to start adding a tweet at the end of each round-up. We'll start with this one:

+ + + +
+ + + +
+ +
+ +

React v0.5.1 @@ -395,109 +533,6 @@ -

- -
- - -

- - Community Round-up #7 - -

- -

- August 26, 2013 - by - - - Vjeux - - - -

- -
- -
-

It's been three months since we open sourced React and it is going well. Some stats so far:

- - -

Wolfenstein Rendering Engine Ported to React #

-

Pete Hunt ported the render code of the web version of Wolfenstein 3D to React. Check out the demo and render.js file for the implementation. -

-

React & Meteor #

-

Ben Newman made a 13-lines wrapper to use React and Meteor together. Meteor handles the real-time data synchronization between client and server. React provides the declarative way to write the interface and only updates the parts of the UI that changed.

- -
-

This repository defines a Meteor package that automatically integrates the React rendering framework on both the client and the server, to complement or replace the default Handlebars templating system.

- -

The React core is officially agnostic about how you fetch and update your data, so it is far from obvious which approach is the best. This package provides one answer to that question (use Meteor!), and I hope you will find it a compelling combination.

-
var MyComponent = React.createClass({
- mixins: [MeteorMixin],
-
- getMeteorState: function() {
-   return { foo: Session.get('foo') };
- },
-
- render: function() {
-   return <div>{this.state.foo}</div>;
- }
-});
-
-

Dependencies will be registered for any data accesses performed by getMeteorState so that the component can be automatically re-rendered whenever the data changes.

- -

Read more ...

-
-

React Page #

-

Jordan Walke implemented a complete React project creator called react-page. It supports both server-side and client-side rendering, source transform and packaging JSX files using CommonJS modules, and instant reload.

- -
-

Easy Application Development with React JavaScript -

- -

Why Server Rendering?

- -
    -
  • Faster initial page speed: - -
      -
    • Markup displayed before downloading large JavaScript.
    • -
    • Markup can be generated more quickly on a fast server than low power client devices.
    • -
  • -
  • Faster Development and Prototyping: - -
      -
    • Instantly refresh your app without waiting for any watch scripts or bundlers.
    • -
  • -
  • Easy deployment of static content pages/blogs: just archive using recursive wget.
  • -
  • SEO benefits of indexability and perf.
  • -
- -

How Does Server Rendering Work?

- -
    -
  • react-page computes page markup on the server, sends it to the client so the user can see it quickly.
  • -
  • The corresponding JavaScript is then packaged and sent.
  • -
  • The browser runs that JavaScript, so that all of the event handlers, interactions and update code will run seamlessly on top of the server generated markup.
  • -
  • From the developer's (and the user's) perspective, it's just as if the rendering occurred on the client, only faster.
  • -
- -

Try it out ...

-
- -
- - -
diff --git a/blog/page17/index.html b/blog/page17/index.html index bab5de3aa7..0064de0936 100644 --- a/blog/page17/index.html +++ b/blog/page17/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,109 @@
+

+ + Community Round-up #7 + +

+ +

+ August 26, 2013 + by + + + Vjeux + + + +

+ +
+ +
+

It's been three months since we open sourced React and it is going well. Some stats so far:

+ + +

Wolfenstein Rendering Engine Ported to React #

+

Pete Hunt ported the render code of the web version of Wolfenstein 3D to React. Check out the demo and render.js file for the implementation. +

+

React & Meteor #

+

Ben Newman made a 13-lines wrapper to use React and Meteor together. Meteor handles the real-time data synchronization between client and server. React provides the declarative way to write the interface and only updates the parts of the UI that changed.

+ +
+

This repository defines a Meteor package that automatically integrates the React rendering framework on both the client and the server, to complement or replace the default Handlebars templating system.

+ +

The React core is officially agnostic about how you fetch and update your data, so it is far from obvious which approach is the best. This package provides one answer to that question (use Meteor!), and I hope you will find it a compelling combination.

+
var MyComponent = React.createClass({
+ mixins: [MeteorMixin],
+
+ getMeteorState: function() {
+   return { foo: Session.get('foo') };
+ },
+
+ render: function() {
+   return <div>{this.state.foo}</div>;
+ }
+});
+
+

Dependencies will be registered for any data accesses performed by getMeteorState so that the component can be automatically re-rendered whenever the data changes.

+ +

Read more ...

+
+

React Page #

+

Jordan Walke implemented a complete React project creator called react-page. It supports both server-side and client-side rendering, source transform and packaging JSX files using CommonJS modules, and instant reload.

+ +
+

Easy Application Development with React JavaScript +

+ +

Why Server Rendering?

+ +
    +
  • Faster initial page speed: + +
      +
    • Markup displayed before downloading large JavaScript.
    • +
    • Markup can be generated more quickly on a fast server than low power client devices.
    • +
  • +
  • Faster Development and Prototyping: + +
      +
    • Instantly refresh your app without waiting for any watch scripts or bundlers.
    • +
  • +
  • Easy deployment of static content pages/blogs: just archive using recursive wget.
  • +
  • SEO benefits of indexability and perf.
  • +
+ +

How Does Server Rendering Work?

+ +
    +
  • react-page computes page markup on the server, sends it to the client so the user can see it quickly.
  • +
  • The corresponding JavaScript is then packaged and sent.
  • +
  • The browser runs that JavaScript, so that all of the event handlers, interactions and update code will run seamlessly on top of the server generated markup.
  • +
  • From the developer's (and the user's) perspective, it's just as if the rendering occurred on the client, only faster.
  • +
+ +

Try it out ...

+
+ +
+ + + +
+ +
+ +

Use React and JSX in Python Applications @@ -352,125 +455,6 @@ -

- -
- - -

- - Community Round-up #5 - -

- -

- July 23, 2013 - by - - - Vjeux - - - -

- -
- -
-

We launched the React Facebook Page along with the React v0.4 launch. 700 people already liked it to get updated on the project :)

-

Cross-browser onChange #

-

Ben Alpert from Khan Academy worked on a cross-browser implementation of onChange event that landed in v0.4. He wrote a blog post explaining the various browser quirks he had to deal with.

- -
-

First off, what is the input event? If you have an <input> element and want to receive events whenever the value changes, the most obvious thing to do is to listen to the change event. Unfortunately, change fires only after the text field is defocused, rather than on each keystroke. The next obvious choice is the keyup event, which is triggered whenever a key is released. Unfortunately, keyup doesn't catch input that doesn't involve the keyboard (e.g., pasting from the clipboard using the mouse) and only fires once if a key is held down, rather than once per inserted character.

- -

Both keydown and keypress do fire repeatedly when a key is held down, but both fire immediately before the value changes, so to read the new value you have to defer the handler to the next event loop using setTimeout(fn, 0) or similar, which slows down your app. Of course, like keyup, neither keydown nor keypress fires for non-keyboard input events, and all three can fire in cases where the value doesn't change at all (such as when pressing the arrow keys).

- -

Read the full post...

-
-

React Samples #

-

Learning a new library is always easier when you have working examples you can play with. jwh put many of them on his react-samples Github repo.

- -
-

Some simple examples with Facebook's React framework

- - -
-

React Chosen Wrapper #

-

Cheng Lou wrote a wrapper for the Chosen input library called react-chosen. It took just 25 lines to be able to use jQuery component as a React one.

-
React.renderComponent(
-  <Chosen noResultsText="No result" value="Harvest" onChange={doSomething}>
-    <option value="Facebook">Facebook</option>
-    <option value="Harvest">Harvest</option>
-  </Chosen>
-, document.getElementById('example'));
-

JSX and ES6 Template Strings #

-

Domenic Denicola wrote a slide deck about the great applications of ES6 features and one slide shows how we could use Template Strings to compile JSX at run-time without the need for a pre-processing phase.

- -
-

React Presentation #

-

Tom Occhino and Jordan Walke, React developers, did a presentation of React at Facebook Seattle's office. Check out the first 25 minutes for the presentation and the remaining 45 for a Q&A. I highly recommend you watching this video.

- -
-

Docs #

-

Pete Hunt rewrote the entirety of the docs for v0.4. The goal was to add more explanation about why we built React and what the best practices are.

- -
-

Guides

- - -
- -
- - -
diff --git a/blog/page18/index.html b/blog/page18/index.html index d9e95096a4..a9886265fd 100644 --- a/blog/page18/index.html +++ b/blog/page18/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,125 @@
+

+ + Community Round-up #5 + +

+ +

+ July 23, 2013 + by + + + Vjeux + + + +

+ +
+ +
+

We launched the React Facebook Page along with the React v0.4 launch. 700 people already liked it to get updated on the project :)

+

Cross-browser onChange #

+

Ben Alpert from Khan Academy worked on a cross-browser implementation of onChange event that landed in v0.4. He wrote a blog post explaining the various browser quirks he had to deal with.

+ +
+

First off, what is the input event? If you have an <input> element and want to receive events whenever the value changes, the most obvious thing to do is to listen to the change event. Unfortunately, change fires only after the text field is defocused, rather than on each keystroke. The next obvious choice is the keyup event, which is triggered whenever a key is released. Unfortunately, keyup doesn't catch input that doesn't involve the keyboard (e.g., pasting from the clipboard using the mouse) and only fires once if a key is held down, rather than once per inserted character.

+ +

Both keydown and keypress do fire repeatedly when a key is held down, but both fire immediately before the value changes, so to read the new value you have to defer the handler to the next event loop using setTimeout(fn, 0) or similar, which slows down your app. Of course, like keyup, neither keydown nor keypress fires for non-keyboard input events, and all three can fire in cases where the value doesn't change at all (such as when pressing the arrow keys).

+ +

Read the full post...

+
+

React Samples #

+

Learning a new library is always easier when you have working examples you can play with. jwh put many of them on his react-samples Github repo.

+ +
+

Some simple examples with Facebook's React framework

+ + +
+

React Chosen Wrapper #

+

Cheng Lou wrote a wrapper for the Chosen input library called react-chosen. It took just 25 lines to be able to use jQuery component as a React one.

+
React.renderComponent(
+  <Chosen noResultsText="No result" value="Harvest" onChange={doSomething}>
+    <option value="Facebook">Facebook</option>
+    <option value="Harvest">Harvest</option>
+  </Chosen>
+, document.getElementById('example'));
+

JSX and ES6 Template Strings #

+

Domenic Denicola wrote a slide deck about the great applications of ES6 features and one slide shows how we could use Template Strings to compile JSX at run-time without the need for a pre-processing phase.

+ +
+

React Presentation #

+

Tom Occhino and Jordan Walke, React developers, did a presentation of React at Facebook Seattle's office. Check out the first 25 minutes for the presentation and the remaining 45 for a Q&A. I highly recommend you watching this video.

+ +
+

Docs #

+

Pete Hunt rewrote the entirety of the docs for v0.4. The goal was to add more explanation about why we built React and what the best practices are.

+ +
+

Guides

+ + +
+ +
+ + + +
+ +
+ +

React v0.4.0 @@ -377,110 +496,6 @@ If you were using React without JSX previously, your code should still work. - -
- - -

- - Community Round-up #3 - -

- -

- June 27, 2013 - by - - - Vjeux - - - -

- -
- -
-

The highlight of this week is that an interaction-heavy app has been ported to React. React components are solving issues they had with nested views.

-

Moving From Backbone To React #

-

Clay Allsopp successfully ported Propeller, a fairly big, interaction-heavy JavaScript app, to React.

- -
-

Subviews involve a lot of easy-to-forget boilerplate that Backbone (by design) doesn't automate. Libraries like Backbone.Marionette offer more abstractions to make view nesting easier, but they're all limited by the fact that Backbone delegates how and went view-document attachment occurs to the application code.

- -

React, on the other hand, manages the DOM and only exposes real nodes at select points in its API. The "elements" you code in React are actually objects which wrap DOM nodes, not the actual objects which get inserted into the DOM. Internally, React converts those abstractions into actual DOMElements and fills out the document accordingly. [...]

- -

We moved about 20 different Backbone view classes to React over the past few weeks, including the live-preview pane that you see in our little iOS demo. Most importantly, it's allowed us to put energy into making each component work great on its own, instead of spending extra cycles to ensure they function in unison. For that reason, we think React is a more scalable way to build view-intensive apps than Backbone alone, and it doesn't require you to drop-everything-and-refactor like a move to Ember or Angular would demand.

- -

Read the full post...

-
-

Grunt Task for JSX #

-

Eric Clemmons wrote a task for Grunt that applies the JSX transformation to your Javascript files. It also works with Browserify if you want all your files to be concatenated and minified together.

- -
-

Grunt task for compiling Facebook React's .jsx templates into .js

-
grunt.initConfig({
-  react: {
-    app: {
-      options: { extension: 'js' },
-      files: { 'path/to/output/dir': 'path/to/jsx/templates/dir' }
-
-

It also works great with grunt-browserify!

-
browserify: {
-  options: {
-    transform: [ require('grunt-react').browserify ]
-  },
-  app: {
-    src: 'path/to/source/main.js',
-    dest: 'path/to/target/output.js'
-
-

Check out the project ...

-
-

Backbone/Handlebars Nested Views #

-

Joel Burget wrote a blog post talking about the way we would write React-like components in Backbone and Handlebars.

- -
-

The problem here is that we're trying to maniplate a tree, but there's a textual layer we have to go through. Our views are represented as a tree - the subviews are children of CommentCollectionView - and they end up as part of a tree in the DOM. But there's a Handlebars layer in the middle (which deals in flat strings), so the hierarchy must be destructed and rebuilt when we render.

- -

What does it take to render a collection view? In the Backbone/Handlebars view of the world you have to render the template (with stubs), render each subview which replaces a stub, and keep a reference to each subview (or anything within the view that could change in the future).

- -

So while our view is conceptually hierarchical, due to the fact that it has to go through a flat textual representation, we need to do a lot of extra work to reassemble that structure after rendering.

- -

Read the full post...

-
-

JSRomandie Meetup #

-

Renault John Lecoultre from BugBuster did a React introduction talk at a JS meetup called JS Romandie last week.

- - -

CoffeeScript integration #

-

Vjeux used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript.

- -
-

Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable.

-
{div, h3, textarea} = React.DOM
-(div {className: 'MarkdownEditor'}, [
-  (h3 {}, 'Input'),
-  (textarea {onKeyUp: @handleKeyUp, ref: 'textarea'},
-    @state.value
-  )
-])
-
-

Read the full post...

-
-

Tutorial in Plain Javascript #

-

We've seen a lot of people comparing React with various frameworks. Ricardo Tomasi decided to re-implement the tutorial without any framework, just plain Javascript.

- -
-

Facebook & Instagram launched the React framework and an accompanying tutorial. Developer Vlad Yazhbin decided to rewrite that using AngularJS. The end result is pretty neat, but if you're like me you will not actually appreciate the HTML speaking for itself and doing all the hard work. So let's see what that looks like in plain javascript.

- -

Read the full post...

-
- -
- - -
diff --git a/blog/page19/index.html b/blog/page19/index.html index 480aef44ee..36d46f0709 100644 --- a/blog/page19/index.html +++ b/blog/page19/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,110 @@
+

+ + Community Round-up #3 + +

+ +

+ June 27, 2013 + by + + + Vjeux + + + +

+ +
+ +
+

The highlight of this week is that an interaction-heavy app has been ported to React. React components are solving issues they had with nested views.

+

Moving From Backbone To React #

+

Clay Allsopp successfully ported Propeller, a fairly big, interaction-heavy JavaScript app, to React.

+ +
+

Subviews involve a lot of easy-to-forget boilerplate that Backbone (by design) doesn't automate. Libraries like Backbone.Marionette offer more abstractions to make view nesting easier, but they're all limited by the fact that Backbone delegates how and went view-document attachment occurs to the application code.

+ +

React, on the other hand, manages the DOM and only exposes real nodes at select points in its API. The "elements" you code in React are actually objects which wrap DOM nodes, not the actual objects which get inserted into the DOM. Internally, React converts those abstractions into actual DOMElements and fills out the document accordingly. [...]

+ +

We moved about 20 different Backbone view classes to React over the past few weeks, including the live-preview pane that you see in our little iOS demo. Most importantly, it's allowed us to put energy into making each component work great on its own, instead of spending extra cycles to ensure they function in unison. For that reason, we think React is a more scalable way to build view-intensive apps than Backbone alone, and it doesn't require you to drop-everything-and-refactor like a move to Ember or Angular would demand.

+ +

Read the full post...

+
+

Grunt Task for JSX #

+

Eric Clemmons wrote a task for Grunt that applies the JSX transformation to your Javascript files. It also works with Browserify if you want all your files to be concatenated and minified together.

+ +
+

Grunt task for compiling Facebook React's .jsx templates into .js

+
grunt.initConfig({
+  react: {
+    app: {
+      options: { extension: 'js' },
+      files: { 'path/to/output/dir': 'path/to/jsx/templates/dir' }
+
+

It also works great with grunt-browserify!

+
browserify: {
+  options: {
+    transform: [ require('grunt-react').browserify ]
+  },
+  app: {
+    src: 'path/to/source/main.js',
+    dest: 'path/to/target/output.js'
+
+

Check out the project ...

+
+

Backbone/Handlebars Nested Views #

+

Joel Burget wrote a blog post talking about the way we would write React-like components in Backbone and Handlebars.

+ +
+

The problem here is that we're trying to maniplate a tree, but there's a textual layer we have to go through. Our views are represented as a tree - the subviews are children of CommentCollectionView - and they end up as part of a tree in the DOM. But there's a Handlebars layer in the middle (which deals in flat strings), so the hierarchy must be destructed and rebuilt when we render.

+ +

What does it take to render a collection view? In the Backbone/Handlebars view of the world you have to render the template (with stubs), render each subview which replaces a stub, and keep a reference to each subview (or anything within the view that could change in the future).

+ +

So while our view is conceptually hierarchical, due to the fact that it has to go through a flat textual representation, we need to do a lot of extra work to reassemble that structure after rendering.

+ +

Read the full post...

+
+

JSRomandie Meetup #

+

Renault John Lecoultre from BugBuster did a React introduction talk at a JS meetup called JS Romandie last week.

+ + +

CoffeeScript integration #

+

Vjeux used the fact that JSX is just a syntactic sugar on-top of regular JS to rewrite the React front-page examples in CoffeeScript.

+ +
+

Multiple people asked what's the story about JSX and CoffeeScript. There is no JSX pre-processor for CoffeeScript and I'm not aware of anyone working on it. Fortunately, CoffeeScript is pretty expressive and we can play around the syntax to come up with something that is usable.

+
{div, h3, textarea} = React.DOM
+(div {className: 'MarkdownEditor'}, [
+  (h3 {}, 'Input'),
+  (textarea {onKeyUp: @handleKeyUp, ref: 'textarea'},
+    @state.value
+  )
+])
+
+

Read the full post...

+
+

Tutorial in Plain Javascript #

+

We've seen a lot of people comparing React with various frameworks. Ricardo Tomasi decided to re-implement the tutorial without any framework, just plain Javascript.

+ +
+

Facebook & Instagram launched the React framework and an accompanying tutorial. Developer Vlad Yazhbin decided to rewrite that using AngularJS. The end result is pretty neat, but if you're like me you will not actually appreciate the HTML speaking for itself and doing all the hard work. So let's see what that looks like in plain javascript.

+ +

Read the full post...

+
+ +
+ + + +
+ +
+ +

React v0.3.3 @@ -415,41 +519,6 @@ but if you are interested in the nuts and bolts -

- -
- - -

- - JSFiddle Integration - -

- -

- June 2, 2013 - by - - - Vjeux - - - -

- -
- -
-

JSFiddle just announced support for React. This is an exciting news as it makes collaboration on snippets of code a lot easier. You can play around this base React JSFiddle, fork it and share it! A fiddle without JSX is also available.

- - - - - -
- - -
@@ -460,6 +529,10 @@ but if you are interested in the nuts and bolts + + diff --git a/blog/page2/index.html b/blog/page2/index.html index 5ed0b358ea..01133df7a8 100644 --- a/blog/page2/index.html +++ b/blog/page2/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,75 @@
+

+ + React v0.14.3 + +

+ +

+ November 18, 2015 + by + + + Paul O’Shannessy + + + +

+ +
+ +
+

It's time for another installment of React patch releases! We didn't break anything in v0.14.2 but we do have a couple of other bugs we're fixing. The biggest change in this release is actually an addition of a new built file. We heard from a number of people that they still need the ability to use React to render to a string on the client. While the use cases are not common and there are other ways to achieve this, we decided that it's still valuable to support. So we're now building react-dom-server.js, which will be shipped to Bower and in the dist/ directory of the react-dom package on npm. This file works the same way as react-dom.js and therefore requires that the primary React build has already been included on the page.

+ +

The release is now available for download:

+ + + +

We've also published version 0.14.3 of the react, react-dom, and addons packages on npm and the react package on bower.

+ +
+

Changelog #

React DOM #

+
    +
  • Added support for nonce attribute for <script> and <style> elements
  • +
  • Added support for reversed attribute for <ol> elements
  • +
+

React TestUtils Add-on #

+
    +
  • Fixed bug with shallow rendering and function refs
  • +
+

React CSSTransitionGroup Add-on #

+
    +
  • Fixed bug resulting in timeouts firing incorrectly when mounting and unmounting rapidly
  • +
+

React on Bower #

+
    +
  • Added react-dom-server.js to expose renderToString and renderToStaticMarkup for usage in the browser
  • +
+ +
+ + + +
+ +
+ +

React v0.14.2 @@ -512,148 +581,6 @@ Minified build for production: h -

- -
- - -

- - ReactDOM.render and the Top Level React API - -

- -

- October 1, 2015 - by - - - Jim Sproch - - and - - - Sebastian Markbåge - - - -

- -
- -
-

When you're in React's world you are just building components that fit into other components. Everything is a component. Unfortunately not everything around you is built using React. At the root of your tree you still have to write some plumbing code to connect the outer world into React.

- -

The primary API for rendering into the DOM looks like this:

-
ReactDOM.render(reactElement, domContainerNode)
-
-

To update the properties of an existing component, you call render again with a new element.

- -

If you are rendering React components within a single-page app, you may need to plug into the app's view lifecycle to ensure your app will invoke unmountComponentAtNode at the appropriate time. React will not automatically clean up a tree. You need to manually call:

-
ReactDOM.unmountComponentAtNode(domContainerNode)
-
-

This is important and often forgotten. Forgetting to call unmountComponentAtNode will cause your app to leak memory. There is no way for us to automatically detect when it is appropriate to do this work. Every system is different.

- -

It is not unique to the DOM. If you want to insert a React Native view in the middle of an existing iOS app you will hit similar issues.

-

Helpers #

-

If you have multiple React roots, or a single root that gets deleted over time, we recommend that you always create your own wrapper API. These will all look slightly different depending on what your outer system looks like. For example, at Facebook we have a system that automatically ties into our page transition router to automatically call unmountComponentAtNode.

- -

Rather than calling ReactDOM.render() directly everywhere, consider writing/using a library that will manage mounting and unmounting within your application.

- -

In your environment you may want to always configure internationalization, routers, user data etc. If you have many different React roots it can be a pain to set up configuration nodes all over the place. By creating your own wrapper you can unify that configuration into one place.

-

Object Oriented Updates #

-

If you call ReactDOM.render a second time to update properties, all your props are completely replaced.

-
ReactDOM.render(<App locale="en-US" userID={1} />, container);
-// props.userID == 1
-// props.locale == "en-US"
-ReactDOM.render(<App userID={2} />, container);
-// props.userID == 2
-// props.locale == undefined ??!?
-
-

In object-oriented programming, all state lives on each object instance and you apply changes incrementally by mutating that state, one piece at a time. If you are using React within an app that expects an object oriented API (for instance, if you are building a custom web component using React), it might be surprising/confusing to a user that setting a single property would wipe out all the other properties on your component.

- -

We used to have a helper function called setProps which allowed you to update only a few properties at a time. Unfortunately this API lived on a component instance, required React to keep this state internally and wasn't very natural anyway. Therefore, we're deprecating it and suggest that you build it into your own wrapper instead.

- -

Here's some boilerplate to get you started. It is a 0.14 migration path for codebases using setProps and replaceProps.

-
class ReactComponentRenderer {
-  constructor(klass, container) {
-    this.klass = klass;
-    this.container = container;
-    this.props = {};
-    this.component = null;
-  }
-
-  replaceProps(props, callback) {
-    this.props = {};
-    this.setProps(props, callback);
-  }
-
-  setProps(partialProps, callback) {
-    if (this.klass == null) {
-      console.warn(
-        'setProps(...): Can only update a mounted or ' +
-        'mounting component. This usually means you called setProps() on ' +
-        'an unmounted component. This is a no-op.'
-      );
-      return;
-    }
-    Object.assign(this.props, partialProps);
-    var element = React.createElement(this.klass, this.props);
-    this.component = ReactDOM.render(element, this.container, callback);
-  }
-
-  unmount() {
-    ReactDOM.unmountComponentAtNode(this.container);
-    this.klass = null;
-  }
-}
-
-

Object-oriented APIs don't look like that though. They use setters and methods. I think we can do better. If you know more about the component API that you're rendering, you can create a more natural object-oriented API around your React component.

-
class ReactVideoPlayer {
-  constructor(url, container) {
-    this._container = container;
-    this._url = url;
-    this._isPlaying = false;
-    this._render();
-  }
-
-  _render() {
-    ReactDOM.render(
-      <VideoPlayer url={this._url} playing={this._isPlaying} />,
-      this._container
-    );
-  }
-
-  get url() {
-    return this._url;
-  }
-
-  set url(value) {
-    this._url = value;
-    this._render();
-  }
-
-  play() {
-    this._isPlaying = true;
-    this._render();
-  }
-
-  pause() {
-    this._isPlaying = false;
-    this._render();
-  }
-
-  destroy() {
-    ReactDOM.unmountComponentAtNode(this._container);
-  }
-}
-
-

This example shows how to provide an imperative API on top of a declarative one. Similarly, the reverse can be done, and a declarative wrapper can be used when exposing a Web Component as a React component.

- -
- - -
diff --git a/blog/page20/index.html b/blog/page20/index.html new file mode 100644 index 0000000000..93e2da17fa --- /dev/null +++ b/blog/page20/index.html @@ -0,0 +1,177 @@ + + + + + + + Blog | React + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+ +
+ + +

+ + JSFiddle Integration + +

+ +

+ June 2, 2013 + by + + + Vjeux + + + +

+ +
+ +
+

JSFiddle just announced support for React. This is an exciting news as it makes collaboration on snippets of code a lot easier. You can play around this base React JSFiddle, fork it and share it! A fiddle without JSX is also available.

+ + + + + +
+ + + +
+ + + +
+
+ + +
+
+ A Facebook & Instagram collaboration.
+ Acknowledgements +
+
+ © 2013–2016 Facebook Inc.
+ Documentation licensed under CC BY 4.0. +
+
+
+
+ + + + diff --git a/blog/page3/index.html b/blog/page3/index.html index 809db7e071..fd38df5fc1 100644 --- a/blog/page3/index.html +++ b/blog/page3/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,148 @@
+

+ + ReactDOM.render and the Top Level React API + +

+ +

+ October 1, 2015 + by + + + Jim Sproch + + and + + + Sebastian Markbåge + + + +

+ +
+ +
+

When you're in React's world you are just building components that fit into other components. Everything is a component. Unfortunately not everything around you is built using React. At the root of your tree you still have to write some plumbing code to connect the outer world into React.

+ +

The primary API for rendering into the DOM looks like this:

+
ReactDOM.render(reactElement, domContainerNode)
+
+

To update the properties of an existing component, you call render again with a new element.

+ +

If you are rendering React components within a single-page app, you may need to plug into the app's view lifecycle to ensure your app will invoke unmountComponentAtNode at the appropriate time. React will not automatically clean up a tree. You need to manually call:

+
ReactDOM.unmountComponentAtNode(domContainerNode)
+
+

This is important and often forgotten. Forgetting to call unmountComponentAtNode will cause your app to leak memory. There is no way for us to automatically detect when it is appropriate to do this work. Every system is different.

+ +

It is not unique to the DOM. If you want to insert a React Native view in the middle of an existing iOS app you will hit similar issues.

+

Helpers #

+

If you have multiple React roots, or a single root that gets deleted over time, we recommend that you always create your own wrapper API. These will all look slightly different depending on what your outer system looks like. For example, at Facebook we have a system that automatically ties into our page transition router to automatically call unmountComponentAtNode.

+ +

Rather than calling ReactDOM.render() directly everywhere, consider writing/using a library that will manage mounting and unmounting within your application.

+ +

In your environment you may want to always configure internationalization, routers, user data etc. If you have many different React roots it can be a pain to set up configuration nodes all over the place. By creating your own wrapper you can unify that configuration into one place.

+

Object Oriented Updates #

+

If you call ReactDOM.render a second time to update properties, all your props are completely replaced.

+
ReactDOM.render(<App locale="en-US" userID={1} />, container);
+// props.userID == 1
+// props.locale == "en-US"
+ReactDOM.render(<App userID={2} />, container);
+// props.userID == 2
+// props.locale == undefined ??!?
+
+

In object-oriented programming, all state lives on each object instance and you apply changes incrementally by mutating that state, one piece at a time. If you are using React within an app that expects an object oriented API (for instance, if you are building a custom web component using React), it might be surprising/confusing to a user that setting a single property would wipe out all the other properties on your component.

+ +

We used to have a helper function called setProps which allowed you to update only a few properties at a time. Unfortunately this API lived on a component instance, required React to keep this state internally and wasn't very natural anyway. Therefore, we're deprecating it and suggest that you build it into your own wrapper instead.

+ +

Here's some boilerplate to get you started. It is a 0.14 migration path for codebases using setProps and replaceProps.

+
class ReactComponentRenderer {
+  constructor(klass, container) {
+    this.klass = klass;
+    this.container = container;
+    this.props = {};
+    this.component = null;
+  }
+
+  replaceProps(props, callback) {
+    this.props = {};
+    this.setProps(props, callback);
+  }
+
+  setProps(partialProps, callback) {
+    if (this.klass == null) {
+      console.warn(
+        'setProps(...): Can only update a mounted or ' +
+        'mounting component. This usually means you called setProps() on ' +
+        'an unmounted component. This is a no-op.'
+      );
+      return;
+    }
+    Object.assign(this.props, partialProps);
+    var element = React.createElement(this.klass, this.props);
+    this.component = ReactDOM.render(element, this.container, callback);
+  }
+
+  unmount() {
+    ReactDOM.unmountComponentAtNode(this.container);
+    this.klass = null;
+  }
+}
+
+

Object-oriented APIs don't look like that though. They use setters and methods. I think we can do better. If you know more about the component API that you're rendering, you can create a more natural object-oriented API around your React component.

+
class ReactVideoPlayer {
+  constructor(url, container) {
+    this._container = container;
+    this._url = url;
+    this._isPlaying = false;
+    this._render();
+  }
+
+  _render() {
+    ReactDOM.render(
+      <VideoPlayer url={this._url} playing={this._isPlaying} />,
+      this._container
+    );
+  }
+
+  get url() {
+    return this._url;
+  }
+
+  set url(value) {
+    this._url = value;
+    this._render();
+  }
+
+  play() {
+    this._isPlaying = true;
+    this._render();
+  }
+
+  pause() {
+    this._isPlaying = false;
+    this._render();
+  }
+
+  destroy() {
+    ReactDOM.unmountComponentAtNode(this._container);
+  }
+}
+
+

This example shows how to provide an imperative API on top of a declarative one. Similarly, the reverse can be done, and a declarative wrapper can be used when exposing a Web Component as a React component.

+ +
+ + + +
+ +
+ +

Community Round-up #27 – Relay Edition @@ -511,61 +653,6 @@ Minified build for production: - - -

- - Relay Technical Preview - -

- -

- August 11, 2015 - by - - - Joseph Savona - - - -

- -
- -
-

Relay #

-

Today we're excited to share an update on Relay - the technical preview is now open-source and available on GitHub.

-

Why Relay #

-

While React simplified the process of developing complex user-interfaces, it left open the question of how to interact with data on the server. It turns out that this was a significant source of friction for our developers; fragile coupling between client and server caused data-related bugs and made iteration harder. Furthermore, developers were forced to constantly re-implement complex async logic instead of focusing on their apps. Relay addresses these concerns by borrowing important lessons from React: it provides declarative, component-oriented data fetching for React applications.

- -

Declarative data-fetching means that Relay applications specify what data they need, not how to fetch that data. Just as React uses a description of the desired UI to manage view updates, Relay uses a data description in the form of GraphQL queries. Given these descriptions, Relay coalesces queries into batches for efficiency, manages error-prone asynchronous logic, caches data for performance, and automatically updates views as data changes.

- -

Relay is also component-oriented, extending the notion of a React component to include a description of what data is necessary to render it. This colocation allows developers to reason locally about their application and eliminates bugs such as under- or over-fetching data.

- -

Relay is in use at Facebook in production apps, and we're using it more and more because Relay lets developers focus on their products and move fast. It's working for us and we'd like to share it with the community.

-

What's Included #

-

We're open-sourcing a technical preview of Relay - the core framework that we use internally, with some modifications for use outside Facebook. As this is the first release, it's good to keep in mind that there may be some incomplete or missing features. We'll continue to develop Relay and are working closely with the GraphQL community to ensure that Relay tracks updates during GraphQL's RFC period. But we couldn't wait any longer to get this in your hands, and we're looking forward to your feedback and contributions.

- -

Relay is available on GitHub and npm.

-

What's Next #

-

The team is super excited to be releasing Relay - and just as excited about what's next. Here are some of the things we'll be focusing on:

- -
    -
  • Offline support. This will allow applications to fulfill queries and enqueue updates without connectivity.
  • -
  • Real-time updates. In collaboration with the GraphQL community, we're working to define a specification for subscriptions and provide support for them in Relay.
  • -
  • A generic Relay. Just as the power of React was never about the virtual DOM, Relay is much more than a GraphQL client. We're working to extend Relay to provide a unified interface for interacting not only with server data, but also in-memory and native device data (and, even better, a mix of all three).
  • -
  • Finally, it's all too easy as developers to focus on those people with the newest devices and fastest internet connections. We're working to make it easier to build applications that are robust in the face of slow or intermittent connectivity.
  • -
- -

Thanks!

- -
- - -

diff --git a/blog/page4/index.html b/blog/page4/index.html index 057e6e78bc..34cc7ce301 100644 --- a/blog/page4/index.html +++ b/blog/page4/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,61 @@
+

+ + Relay Technical Preview + +

+ +

+ August 11, 2015 + by + + + Joseph Savona + + + +

+ +
+ +
+

Relay #

+

Today we're excited to share an update on Relay - the technical preview is now open-source and available on GitHub.

+

Why Relay #

+

While React simplified the process of developing complex user-interfaces, it left open the question of how to interact with data on the server. It turns out that this was a significant source of friction for our developers; fragile coupling between client and server caused data-related bugs and made iteration harder. Furthermore, developers were forced to constantly re-implement complex async logic instead of focusing on their apps. Relay addresses these concerns by borrowing important lessons from React: it provides declarative, component-oriented data fetching for React applications.

+ +

Declarative data-fetching means that Relay applications specify what data they need, not how to fetch that data. Just as React uses a description of the desired UI to manage view updates, Relay uses a data description in the form of GraphQL queries. Given these descriptions, Relay coalesces queries into batches for efficiency, manages error-prone asynchronous logic, caches data for performance, and automatically updates views as data changes.

+ +

Relay is also component-oriented, extending the notion of a React component to include a description of what data is necessary to render it. This colocation allows developers to reason locally about their application and eliminates bugs such as under- or over-fetching data.

+ +

Relay is in use at Facebook in production apps, and we're using it more and more because Relay lets developers focus on their products and move fast. It's working for us and we'd like to share it with the community.

+

What's Included #

+

We're open-sourcing a technical preview of Relay - the core framework that we use internally, with some modifications for use outside Facebook. As this is the first release, it's good to keep in mind that there may be some incomplete or missing features. We'll continue to develop Relay and are working closely with the GraphQL community to ensure that Relay tracks updates during GraphQL's RFC period. But we couldn't wait any longer to get this in your hands, and we're looking forward to your feedback and contributions.

+ +

Relay is available on GitHub and npm.

+

What's Next #

+

The team is super excited to be releasing Relay - and just as excited about what's next. Here are some of the things we'll be focusing on:

+ +
    +
  • Offline support. This will allow applications to fulfill queries and enqueue updates without connectivity.
  • +
  • Real-time updates. In collaboration with the GraphQL community, we're working to define a specification for subscriptions and provide support for them in Relay.
  • +
  • A generic Relay. Just as the power of React was never about the virtual DOM, Relay is much more than a GraphQL client. We're working to extend Relay to provide a unified interface for interacting not only with server data, but also in-memory and native device data (and, even better, a mix of all three).
  • +
  • Finally, it's all too easy as developers to focus on those people with the newest devices and fastest internet connections. We're working to make it easier to build applications that are robust in the face of slow or intermittent connectivity.
  • +
+ +

Thanks!

+ +
+ + + +
+ +
+ +

New React Devtools Beta @@ -383,69 +438,6 @@ for more info.

-

- -
- - -

- - React v0.13.3 - -

- -

- May 8, 2015 - by - - - Paul O’Shannessy - - - -

- -
- -
-

Today we're sharing another patch release in the v0.13 branch. There are only a few small changes, with a couple to address some issues that arose around that undocumented feature so many of you are already using: context. We also improved developer ergonomics just a little bit, making some warnings better.

- -

The release is now available for download:

- - - -

We've also published version 0.13.3 of the react and react-tools packages on npm and the react package on bower.

- -
-

Changelog #

React Core #

New Features #

-
    -
  • Added clipPath element and attribute for SVG
  • -
  • Improved warnings for deprecated methods in plain JS classes
  • -
-

Bug Fixes #

-
    -
  • Loosened dangerouslySetInnerHTML restrictions so {__html: undefined} will no longer throw
  • -
  • Fixed extraneous context warning with non-pure getChildContext
  • -
  • Ensure replaceState(obj) retains prototype of obj
  • -
-

React with Add-ons #

Bug Fixes #

-
    -
  • Test Utils: Ensure that shallow rendering works when components define contextTypes
  • -
- -
- - -
diff --git a/blog/page5/index.html b/blog/page5/index.html index 6a953db152..6e8736bb75 100644 --- a/blog/page5/index.html +++ b/blog/page5/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,69 @@
+

+ + React v0.13.3 + +

+ +

+ May 8, 2015 + by + + + Paul O’Shannessy + + + +

+ +
+ +
+

Today we're sharing another patch release in the v0.13 branch. There are only a few small changes, with a couple to address some issues that arose around that undocumented feature so many of you are already using: context. We also improved developer ergonomics just a little bit, making some warnings better.

+ +

The release is now available for download:

+ + + +

We've also published version 0.13.3 of the react and react-tools packages on npm and the react package on bower.

+ +
+

Changelog #

React Core #

New Features #

+
    +
  • Added clipPath element and attribute for SVG
  • +
  • Improved warnings for deprecated methods in plain JS classes
  • +
+

Bug Fixes #

+
    +
  • Loosened dangerouslySetInnerHTML restrictions so {__html: undefined} will no longer throw
  • +
  • Fixed extraneous context warning with non-pure getChildContext
  • +
  • Ensure replaceState(obj) retains prototype of obj
  • +
+

React with Add-ons #

Bug Fixes #

+
    +
  • Test Utils: Ensure that shallow rendering works when components define contextTypes
  • +
+ +
+ + + +
+ +
+ +

GraphQL Introduction @@ -414,49 +477,6 @@ Minified build for production: - - -

- - Introducing React Native - -

- -

- March 26, 2015 - by - - - Ben Alpert - - - -

- -
- -
-

In January at React.js Conf, we announced React Native, a new framework for building native apps using React. We're happy to announce that we're open-sourcing React Native and you can start building your apps with it today.

- -

For more details, see Tom Occhino's post on the Facebook Engineering blog:

- -
-

What we really want is the user experience of the native mobile platforms, combined with the developer experience we have when building with React on the web.

- -

With a bit of work, we can make it so the exact same React that's on GitHub can power truly native mobile applications. The only difference in the mobile environment is that instead of running React in the browser and rendering to divs and spans, we run it an embedded instance of JavaScriptCore inside our apps and render to higher-level platform-specific components.

- -

It's worth noting that we're not chasing “write once, run anywhere.” Different platforms have different looks, feels, and capabilities, and as such, we should still be developing discrete apps for each platform, but the same set of engineers should be able to build applications for whatever platform they choose, without needing to learn a fundamentally different set of technologies for each. We call this approach “learn once, write anywhere.”

-
- -

To learn more, visit the React Native website.

- -
- - -

diff --git a/blog/page6/index.html b/blog/page6/index.html index 14f2808b15..f80451a31e 100644 --- a/blog/page6/index.html +++ b/blog/page6/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,49 @@
+

+ + Introducing React Native + +

+ +

+ March 26, 2015 + by + + + Ben Alpert + + + +

+ +
+ +
+

In January at React.js Conf, we announced React Native, a new framework for building native apps using React. We're happy to announce that we're open-sourcing React Native and you can start building your apps with it today.

+ +

For more details, see Tom Occhino's post on the Facebook Engineering blog:

+ +
+

What we really want is the user experience of the native mobile platforms, combined with the developer experience we have when building with React on the web.

+ +

With a bit of work, we can make it so the exact same React that's on GitHub can power truly native mobile applications. The only difference in the mobile environment is that instead of running React in the browser and rendering to divs and spans, we run it an embedded instance of JavaScriptCore inside our apps and render to higher-level platform-specific components.

+ +

It's worth noting that we're not chasing “write once, run anywhere.” Different platforms have different looks, feels, and capabilities, and as such, we should still be developing discrete apps for each platform, but the same set of engineers should be able to build applications for whatever platform they choose, without needing to learn a fundamentally different set of technologies for each. We call this approach “learn once, write anywhere.”

+
+ +

To learn more, visit the React Native website.

+ +
+ + + +
+ +
+ +

Building The Facebook News Feed With Relay @@ -555,84 +598,6 @@ Minified build for production: - - -

- - React v0.13 RC2 - -

- -

- March 3, 2015 - by - - - Sebastian Markbåge - - - -

- -
- -
-

Thanks to everybody who has already been testing the release candidate. We've received some good feedback and as a result we're going to do a second release candidate. The changes are minimal. We haven't changed the behavior of any APIs we exposed in the previous release candidate. Here's a summary of the changes:

- -
    -
  • Introduced a new API (React.cloneElement, see below for details).
  • -
  • Fixed a bug related to validating propTypes when using the new React.addons.createFragment API.
  • -
  • Improved a couple warning messages.
  • -
  • Upgraded jstransform and esprima.
  • -
- -

The release candidate is available for download:

- - - -

We've also published version 0.13.0-rc2 of the react and react-tools packages on npm and the react package on bower.

- -
-

React.cloneElement #

-

In React v0.13 RC2 we will introduce a new API, similar to React.addons.cloneWithProps, with this signature:

-
React.cloneElement(element, props, ...children);
-
-

Unlike cloneWithProps, this new function does not have any magic built-in behavior for merging style and className for the same reason we don't have that feature from transferPropsTo. Nobody is sure what exactly the complete list of magic things are, which makes it difficult to reason about the code and difficult to reuse when style has a different signature (e.g. in the upcoming React Native).

- -

React.cloneElement is almost equivalent to:

-
<element.type {...element.props} {...props}>{children}</element.type>
-
-

However, unlike JSX and cloneWithProps, it also preserves refs. This means that if you get a child with a ref on it, you won't accidentally steal it from your ancestor. You will get the same ref attached to your new element.

- -

One common pattern is to map over your children and add a new prop. There were many issues reported about cloneWithProps losing the ref, making it harder to reason about your code. Now following the same pattern with cloneElement will work as expected. For example:

-
var newChildren = React.Children.map(this.props.children, function(child) {
-  return React.cloneElement(child, { foo: true })
-});
-
-
-

Note: React.cloneElement(child, { ref: 'newRef' }) DOES override the ref so it is still not possible for two parents to have a ref to the same child, unless you use callback-refs.

-
- -

This was a critical feature to get into React 0.13 since props are now immutable. The upgrade path is often to clone the element, but by doing so you might lose the ref. Therefore, we needed a nicer upgrade path here. As we were upgrading callsites at Facebook we realized that we needed this method. We got the same feedback from the community. Therefore we decided to make another RC before the final release to make sure we get this in.

- -

We plan to eventually deprecate React.addons.cloneWithProps. We're not doing it yet, but this is a good opportunity to start thinking about your own uses and consider using React.cloneElement instead. We'll be sure to ship a release with deprecation notices before we actually remove it so no immediate action is necessary.

- -
- - -

diff --git a/blog/page7/index.html b/blog/page7/index.html index fa0f152a47..21b5984655 100644 --- a/blog/page7/index.html +++ b/blog/page7/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,84 @@
+

+ + React v0.13 RC2 + +

+ +

+ March 3, 2015 + by + + + Sebastian Markbåge + + + +

+ +
+ +
+

Thanks to everybody who has already been testing the release candidate. We've received some good feedback and as a result we're going to do a second release candidate. The changes are minimal. We haven't changed the behavior of any APIs we exposed in the previous release candidate. Here's a summary of the changes:

+ +
    +
  • Introduced a new API (React.cloneElement, see below for details).
  • +
  • Fixed a bug related to validating propTypes when using the new React.addons.createFragment API.
  • +
  • Improved a couple warning messages.
  • +
  • Upgraded jstransform and esprima.
  • +
+ +

The release candidate is available for download:

+ + + +

We've also published version 0.13.0-rc2 of the react and react-tools packages on npm and the react package on bower.

+ +
+

React.cloneElement #

+

In React v0.13 RC2 we will introduce a new API, similar to React.addons.cloneWithProps, with this signature:

+
React.cloneElement(element, props, ...children);
+
+

Unlike cloneWithProps, this new function does not have any magic built-in behavior for merging style and className for the same reason we don't have that feature from transferPropsTo. Nobody is sure what exactly the complete list of magic things are, which makes it difficult to reason about the code and difficult to reuse when style has a different signature (e.g. in the upcoming React Native).

+ +

React.cloneElement is almost equivalent to:

+
<element.type {...element.props} {...props}>{children}</element.type>
+
+

However, unlike JSX and cloneWithProps, it also preserves refs. This means that if you get a child with a ref on it, you won't accidentally steal it from your ancestor. You will get the same ref attached to your new element.

+ +

One common pattern is to map over your children and add a new prop. There were many issues reported about cloneWithProps losing the ref, making it harder to reason about your code. Now following the same pattern with cloneElement will work as expected. For example:

+
var newChildren = React.Children.map(this.props.children, function(child) {
+  return React.cloneElement(child, { foo: true })
+});
+
+
+

Note: React.cloneElement(child, { ref: 'newRef' }) DOES override the ref so it is still not possible for two parents to have a ref to the same child, unless you use callback-refs.

+
+ +

This was a critical feature to get into React 0.13 since props are now immutable. The upgrade path is often to clone the element, but by doing so you might lose the ref. Therefore, we needed a nicer upgrade path here. As we were upgrading callsites at Facebook we realized that we needed this method. We got the same feedback from the community. Therefore we decided to make another RC before the final release to make sure we get this in.

+ +

We plan to eventually deprecate React.addons.cloneWithProps. We're not doing it yet, but this is a good opportunity to start thinking about your own uses and consider using React.cloneElement instead. We'll be sure to ship a release with deprecation notices before we actually remove it so no immediate action is necessary.

+ +
+ + + +
+ +
+ +

React v0.13 RC @@ -731,163 +809,6 @@ Minified build for production: - - -

- - React v0.13.0 Beta 1 - -

- -

- January 27, 2015 - by - - - Sebastian Markbåge - - - -

- -
- -
-

React 0.13 has a lot of nice features but there is one particular feature that I'm really excited about. I couldn't wait for React.js Conf to start tomorrow morning.

- -

Maybe you're like me and staying up late excited about the conference, or maybe you weren't one of the lucky ones to get a ticket. Either way I figured I'd give you all something to play with until then.

- -

We just published a beta version of React v0.13.0 to npm! You can install it with npm install react@0.13.0-beta.1. Since this is a pre-release, we don't have proper release notes ready.

- -

So what is that one feature I'm so excited about that I just couldn't wait to share?

-

Plain JavaScript Classes!! #

-

JavaScript originally didn't have a built-in class system. Every popular framework built their own, and so did we. This means that you have a learn slightly different semantics for each framework.

- -

We figured that we're not in the business of designing a class system. We just want to use whatever is the idiomatic JavaScript way of creating classes.

- -

In React 0.13.0 you no longer need to use React.createClass to create React components. If you have a transpiler you can use ES6 classes today. You can use the transpiler we ship with react-tools by making use of the harmony option: jsx --harmony.

-

ES6 Classes #

class HelloMessage extends React.Component {
-  render() {
-    return <div>Hello {this.props.name}</div>;
-  }
-}
-
-React.render(<HelloMessage name="Sebastian" />, mountNode);
-
-

The API is mostly what you would expect, with the exception of getInitialState. We figured that the idiomatic way to specify class state is to just use a simple instance property. Likewise getDefaultProps and propTypes are really just properties on the constructor.

-
export class Counter extends React.Component {
-  constructor(props) {
-    super(props);
-    this.state = {count: props.initialCount};
-  }
-  tick() {
-    this.setState({count: this.state.count + 1});
-  }
-  render() {
-    return (
-      <div onClick={this.tick.bind(this)}>
-        Clicks: {this.state.count}
-      </div>
-    );
-  }
-}
-Counter.propTypes = { initialCount: React.PropTypes.number };
-Counter.defaultProps = { initialCount: 0 };
-

ES7+ Property Initializers #

-

Wait, assigning to properties seems like a very imperative way of defining classes! You're right, however, we designed it this way because it's idiomatic. We fully expect a more declarative syntax for property initialization to arrive in future version of JavaScript. It might look something like this:

-
// Future Version
-export class Counter extends React.Component {
-  static propTypes = { initialCount: React.PropTypes.number };
-  static defaultProps = { initialCount: 0 };
-  state = { count: this.props.initialCount };
-  tick() {
-    this.setState({ count: this.state.count + 1 });
-  }
-  render() {
-    return (
-      <div onClick={this.tick.bind(this)}>
-        Clicks: {this.state.count}
-      </div>
-    );
-  }
-}
-
-

This was inspired by TypeScript's property initializers.

-

Autobinding #

-

React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.

- -

Therefore we decided not to have this built-in into React's class model. You can still explicitly prebind methods in your constructor if you want.

-
class Counter extends React.Component {
-  constructor() {
-    super();
-    this.tick = this.tick.bind(this);
-  }
-  tick() {
-    ...
-  }
-  ...
-}
-
-

However, when we have the future property initializers, there is a neat trick that you can use to accomplish this syntactically:

-
class Counter extends React.Component {
-  tick = () => {
-    ...
-  }
-  ...
-}
-

Mixins #

-

Unfortunately, we will not launch any mixin support for ES6 classes in React. That would defeat the purpose of only using idiomatic JavaScript concepts.

- -

There is no standard and universal way to define mixins in JavaScript. In fact, several features to support mixins were dropped from ES6 today. There are a lot of libraries with different semantics. We think that there should be one way of defining mixins that you can use for any JavaScript class. React just making another doesn't help that effort.

- -

Therefore, we will keep working with the larger JS community to create a standard for mixins. We will also start designing a new compositional API that will help make common tasks easier to do without mixins. E.g. first-class subscriptions to any kind of Flux store.

- -

Luckily, if you want to keep using mixins, you can just keep using React.createClass.

- -
-

Note:

- -

The classic React.createClass style of creating classes will continue to work just fine.

-
-

Other Languages! #

-

Since these classes are just plain old JavaScript classes, you can use other languages that compile to JavaScript classes, such as TypeScript.

- -

You can also use CoffeeScript classes:

-
div = React.createFactory 'div'
-
-class Counter extends React.Component
-  @propTypes = initialCount: React.PropTypes.number
-  @defaultProps = initialCount: 0
-
-  constructor: (props) ->
-    super props
-    @state = count: props.initialCount
-
-  tick: =>
-    @setState count: @state.count + 1
-
-  render: ->
-    div onClick: @tick,
-      'Clicks: '
-      @state.count
-
-

You can even use the old ES3 module pattern if you want:

-
function MyComponent(initialProps) {
-  return {
-    state: { value: initialProps.initialValue },
-    render: function() {
-      return <span className={this.state.value} />
-    }
-  };
-}
-
-
- - -

diff --git a/blog/page8/index.html b/blog/page8/index.html index 10f6776665..3fe7d96fd8 100644 --- a/blog/page8/index.html +++ b/blog/page8/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,163 @@
+

+ + React v0.13.0 Beta 1 + +

+ +

+ January 27, 2015 + by + + + Sebastian Markbåge + + + +

+ +
+ +
+

React 0.13 has a lot of nice features but there is one particular feature that I'm really excited about. I couldn't wait for React.js Conf to start tomorrow morning.

+ +

Maybe you're like me and staying up late excited about the conference, or maybe you weren't one of the lucky ones to get a ticket. Either way I figured I'd give you all something to play with until then.

+ +

We just published a beta version of React v0.13.0 to npm! You can install it with npm install react@0.13.0-beta.1. Since this is a pre-release, we don't have proper release notes ready.

+ +

So what is that one feature I'm so excited about that I just couldn't wait to share?

+

Plain JavaScript Classes!! #

+

JavaScript originally didn't have a built-in class system. Every popular framework built their own, and so did we. This means that you have a learn slightly different semantics for each framework.

+ +

We figured that we're not in the business of designing a class system. We just want to use whatever is the idiomatic JavaScript way of creating classes.

+ +

In React 0.13.0 you no longer need to use React.createClass to create React components. If you have a transpiler you can use ES6 classes today. You can use the transpiler we ship with react-tools by making use of the harmony option: jsx --harmony.

+

ES6 Classes #

class HelloMessage extends React.Component {
+  render() {
+    return <div>Hello {this.props.name}</div>;
+  }
+}
+
+React.render(<HelloMessage name="Sebastian" />, mountNode);
+
+

The API is mostly what you would expect, with the exception of getInitialState. We figured that the idiomatic way to specify class state is to just use a simple instance property. Likewise getDefaultProps and propTypes are really just properties on the constructor.

+
export class Counter extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {count: props.initialCount};
+  }
+  tick() {
+    this.setState({count: this.state.count + 1});
+  }
+  render() {
+    return (
+      <div onClick={this.tick.bind(this)}>
+        Clicks: {this.state.count}
+      </div>
+    );
+  }
+}
+Counter.propTypes = { initialCount: React.PropTypes.number };
+Counter.defaultProps = { initialCount: 0 };
+

ES7+ Property Initializers #

+

Wait, assigning to properties seems like a very imperative way of defining classes! You're right, however, we designed it this way because it's idiomatic. We fully expect a more declarative syntax for property initialization to arrive in future version of JavaScript. It might look something like this:

+
// Future Version
+export class Counter extends React.Component {
+  static propTypes = { initialCount: React.PropTypes.number };
+  static defaultProps = { initialCount: 0 };
+  state = { count: this.props.initialCount };
+  tick() {
+    this.setState({ count: this.state.count + 1 });
+  }
+  render() {
+    return (
+      <div onClick={this.tick.bind(this)}>
+        Clicks: {this.state.count}
+      </div>
+    );
+  }
+}
+
+

This was inspired by TypeScript's property initializers.

+

Autobinding #

+

React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.

+ +

Therefore we decided not to have this built-in into React's class model. You can still explicitly prebind methods in your constructor if you want.

+
class Counter extends React.Component {
+  constructor() {
+    super();
+    this.tick = this.tick.bind(this);
+  }
+  tick() {
+    ...
+  }
+  ...
+}
+
+

However, when we have the future property initializers, there is a neat trick that you can use to accomplish this syntactically:

+
class Counter extends React.Component {
+  tick = () => {
+    ...
+  }
+  ...
+}
+

Mixins #

+

Unfortunately, we will not launch any mixin support for ES6 classes in React. That would defeat the purpose of only using idiomatic JavaScript concepts.

+ +

There is no standard and universal way to define mixins in JavaScript. In fact, several features to support mixins were dropped from ES6 today. There are a lot of libraries with different semantics. We think that there should be one way of defining mixins that you can use for any JavaScript class. React just making another doesn't help that effort.

+ +

Therefore, we will keep working with the larger JS community to create a standard for mixins. We will also start designing a new compositional API that will help make common tasks easier to do without mixins. E.g. first-class subscriptions to any kind of Flux store.

+ +

Luckily, if you want to keep using mixins, you can just keep using React.createClass.

+ +
+

Note:

+ +

The classic React.createClass style of creating classes will continue to work just fine.

+
+

Other Languages! #

+

Since these classes are just plain old JavaScript classes, you can use other languages that compile to JavaScript classes, such as TypeScript.

+ +

You can also use CoffeeScript classes:

+
div = React.createFactory 'div'
+
+class Counter extends React.Component
+  @propTypes = initialCount: React.PropTypes.number
+  @defaultProps = initialCount: 0
+
+  constructor: (props) ->
+    super props
+    @state = count: props.initialCount
+
+  tick: =>
+    @setState count: @state.count + 1
+
+  render: ->
+    div onClick: @tick,
+      'Clicks: '
+      @state.count
+
+

You can even use the old ES3 module pattern if you want:

+
function MyComponent(initialProps) {
+  return {
+    state: { value: initialProps.initialValue },
+    render: function() {
+      return <span className={this.state.value} />
+    }
+  };
+}
+
+
+ + + +
+ +
+ +

React.js Conf Diversity Scholarship @@ -383,148 +540,6 @@ until the next conference. All the talks will be recorded and put online shortly -

- -
- - -

- - React v0.12 - -

- -

- October 28, 2014 - by - - - Paul O’Shannessy - - - -

- -
- -
-

We're happy to announce the availability of React v0.12! After over a week of baking as the release candidate, we uncovered and fixed a few small issues. Thanks to all of you who upgraded and gave us feedback!

- -

We have talked a lot about some of the bigger changes in this release. We introduced new terminology and changed APIs to clean up and simplify some of the concepts of React. We also made several changes to JSX and deprecated a few functions. We won't go into depth about these changes again but we encourage you to read up on these changes in the linked posts. We'll summarize these changes and discuss some of the other changes and how they may impact you below. As always, a full changelog is also included below.

- -

The release is available for download:

- - - -

We've also published version 0.12.0 of the react and react-tools packages on npm and the react package on bower.

-

New Terminology & Updated APIs #

-

v0.12 is bringing about some new terminology. We introduced this 2 weeks ago and we've also documented it in a new section of the documentation. As a part of this, we also corrected many of our top-level APIs to align with the terminology. Component has been removed from all of our React.render* methods. While at one point the argument you passed to these functions was called a Component, it no longer is. You are passing ReactElements. To align with render methods in your component classes, we decided to keep the top-level functions short and sweet. React.renderComponent is now React.render.

- -

We also corrected some other misnomers. React.isValidComponent actually determines if the argument is a ReactElement, so it has been renamed to React.isValidElement. In the same vein, React.PropTypes.component is now React.PropTypes.element and React.PropTypes.renderable is now React.PropTypes.node.

- -

The old methods will still work but will warn upon first use. They will be removed in v0.13.

-

JSX Changes #

-

We talked more in depth about these before, so here are the highlights.

- -
    -
  • No more /** @jsx React.DOM */!
  • -
  • We no longer transform to a straight function call. <Component/> now becomes React.createElement(Component)
  • -
  • DOM components don't make use of React.DOM, instead we pass the tag name directly. <div/> becomes React.createElement('div')
  • -
  • We introduced spread attributes as a quick way to transfer props.
  • -
-

DevTools Improvements, No More __internals #

-

For months we've gotten complaints about the React DevTools message. It shouldn't have logged the up-sell message when you were already using the DevTools. Unfortunately this was because the way we implemented these tools resulted in the DevTools knowing about React, but not the reverse. We finally gave this some attention and enabled React to know if the DevTools are installed. We released an update to the devtools several weeks ago making this possible. Extensions in Chrome should auto-update so you probably already have the update installed!

- -

As a result of this update, we no longer need to expose several internal modules to the world. If you were taking advantage of this implementation detail, your code will break. React.__internals is no more.

-

License Change - BSD #

-

We updated the license on React to the BSD 3-Clause license with an explicit patent grant. Previously we used the Apache 2 license. These licenses are very similar and our extra patent grant is equivalent to the grant provided in the Apache license. You can still use React with the confidence that we have granted the use of any patents covering it. This brings us in line with the same licensing we use across the majority of our open source projects at Facebook.

- -

You can read the full text of the LICENSE and PATENTS files on GitHub.

- -
-

Changelog #

React Core #

Breaking Changes #

-
    -
  • key and ref moved off props object, now accessible on the element directly
  • -
  • React is now BSD licensed with accompanying Patents grant
  • -
  • Default prop resolution has moved to Element creation time instead of mount time, making them effectively static
  • -
  • React.__internals is removed - it was exposed for DevTools which no longer needs access
  • -
  • Composite Component functions can no longer be called directly - they must be wrapped with React.createFactory first. This is handled for you when using JSX.
  • -
-

New Features #

-
    -
  • Spread operator ({...}) introduced to deprecate this.transferPropsTo
  • -
  • Added support for more HTML attributes: acceptCharset, classID, manifest
  • -
-

Deprecations #

-
    -
  • React.renderComponent --> React.render
  • -
  • React.renderComponentToString --> React.renderToString
  • -
  • React.renderComponentToStaticMarkup --> React.renderToStaticMarkup
  • -
  • React.isValidComponent --> React.isValidElement
  • -
  • React.PropTypes.component --> React.PropTypes.element
  • -
  • React.PropTypes.renderable --> React.PropTypes.node
  • -
  • DEPRECATED React.isValidClass
  • -
  • DEPRECATED instance.transferPropsTo
  • -
  • DEPRECATED Returning false from event handlers to preventDefault
  • -
  • DEPRECATED Convenience Constructor usage as function, instead wrap with React.createFactory
  • -
  • DEPRECATED use of key={null} to assign implicit keys
  • -
-

Bug Fixes #

-
    -
  • Better handling of events and updates in nested results, fixing value restoration in "layered" controlled components
  • -
  • Correctly treat event.getModifierState as case sensitive
  • -
  • Improved normalization of event.charCode
  • -
  • Better error stacks when involving autobound methods
  • -
  • Removed DevTools message when the DevTools are installed
  • -
  • Correctly detect required language features across browsers
  • -
  • Fixed support for some HTML attributes: - -
      -
    • list updates correctly now
    • -
    • scrollLeft, scrollTop removed, these should not be specified as props
    • -
  • -
  • Improved error messages
  • -
-

React With Addons #

New Features #

-
    -
  • React.addons.batchedUpdates added to API for hooking into update cycle
  • -
-

Breaking Changes #

-
    -
  • React.addons.update uses assign instead of copyProperties which does hasOwnProperty checks. Properties on prototypes will no longer be updated correctly.
  • -
-

Bug Fixes #

-
    -
  • Fixed some issues with CSS Transitions
  • -
-

JSX #

Breaking Changes #

-
    -
  • Enforced convention: lower case tag names are always treated as HTML tags, upper case tag names are always treated as composite components
  • -
  • JSX no longer transforms to simple function calls
  • -
-

New Features #

-
    -
  • @jsx React.DOM no longer required
  • -
  • spread ({...}) operator introduced to allow easier use of props
  • -
-

Bug Fixes #

-
    -
  • JSXTransformer: Make sourcemaps an option when using APIs directly (eg, for react-rails)
  • -
- -
- - -
diff --git a/blog/page9/index.html b/blog/page9/index.html index f354837f73..f123f4e359 100644 --- a/blog/page9/index.html +++ b/blog/page9/index.html @@ -67,6 +67,8 @@

Recent posts

@@ -97,6 +97,148 @@
+

+ + React v0.12 + +

+ +

+ October 28, 2014 + by + + + Paul O’Shannessy + + + +

+ +
+ +
+

We're happy to announce the availability of React v0.12! After over a week of baking as the release candidate, we uncovered and fixed a few small issues. Thanks to all of you who upgraded and gave us feedback!

+ +

We have talked a lot about some of the bigger changes in this release. We introduced new terminology and changed APIs to clean up and simplify some of the concepts of React. We also made several changes to JSX and deprecated a few functions. We won't go into depth about these changes again but we encourage you to read up on these changes in the linked posts. We'll summarize these changes and discuss some of the other changes and how they may impact you below. As always, a full changelog is also included below.

+ +

The release is available for download:

+ + + +

We've also published version 0.12.0 of the react and react-tools packages on npm and the react package on bower.

+

New Terminology & Updated APIs #

+

v0.12 is bringing about some new terminology. We introduced this 2 weeks ago and we've also documented it in a new section of the documentation. As a part of this, we also corrected many of our top-level APIs to align with the terminology. Component has been removed from all of our React.render* methods. While at one point the argument you passed to these functions was called a Component, it no longer is. You are passing ReactElements. To align with render methods in your component classes, we decided to keep the top-level functions short and sweet. React.renderComponent is now React.render.

+ +

We also corrected some other misnomers. React.isValidComponent actually determines if the argument is a ReactElement, so it has been renamed to React.isValidElement. In the same vein, React.PropTypes.component is now React.PropTypes.element and React.PropTypes.renderable is now React.PropTypes.node.

+ +

The old methods will still work but will warn upon first use. They will be removed in v0.13.

+

JSX Changes #

+

We talked more in depth about these before, so here are the highlights.

+ +
    +
  • No more /** @jsx React.DOM */!
  • +
  • We no longer transform to a straight function call. <Component/> now becomes React.createElement(Component)
  • +
  • DOM components don't make use of React.DOM, instead we pass the tag name directly. <div/> becomes React.createElement('div')
  • +
  • We introduced spread attributes as a quick way to transfer props.
  • +
+

DevTools Improvements, No More __internals #

+

For months we've gotten complaints about the React DevTools message. It shouldn't have logged the up-sell message when you were already using the DevTools. Unfortunately this was because the way we implemented these tools resulted in the DevTools knowing about React, but not the reverse. We finally gave this some attention and enabled React to know if the DevTools are installed. We released an update to the devtools several weeks ago making this possible. Extensions in Chrome should auto-update so you probably already have the update installed!

+ +

As a result of this update, we no longer need to expose several internal modules to the world. If you were taking advantage of this implementation detail, your code will break. React.__internals is no more.

+

License Change - BSD #

+

We updated the license on React to the BSD 3-Clause license with an explicit patent grant. Previously we used the Apache 2 license. These licenses are very similar and our extra patent grant is equivalent to the grant provided in the Apache license. You can still use React with the confidence that we have granted the use of any patents covering it. This brings us in line with the same licensing we use across the majority of our open source projects at Facebook.

+ +

You can read the full text of the LICENSE and PATENTS files on GitHub.

+ +
+

Changelog #

React Core #

Breaking Changes #

+
    +
  • key and ref moved off props object, now accessible on the element directly
  • +
  • React is now BSD licensed with accompanying Patents grant
  • +
  • Default prop resolution has moved to Element creation time instead of mount time, making them effectively static
  • +
  • React.__internals is removed - it was exposed for DevTools which no longer needs access
  • +
  • Composite Component functions can no longer be called directly - they must be wrapped with React.createFactory first. This is handled for you when using JSX.
  • +
+

New Features #

+
    +
  • Spread operator ({...}) introduced to deprecate this.transferPropsTo
  • +
  • Added support for more HTML attributes: acceptCharset, classID, manifest
  • +
+

Deprecations #

+
    +
  • React.renderComponent --> React.render
  • +
  • React.renderComponentToString --> React.renderToString
  • +
  • React.renderComponentToStaticMarkup --> React.renderToStaticMarkup
  • +
  • React.isValidComponent --> React.isValidElement
  • +
  • React.PropTypes.component --> React.PropTypes.element
  • +
  • React.PropTypes.renderable --> React.PropTypes.node
  • +
  • DEPRECATED React.isValidClass
  • +
  • DEPRECATED instance.transferPropsTo
  • +
  • DEPRECATED Returning false from event handlers to preventDefault
  • +
  • DEPRECATED Convenience Constructor usage as function, instead wrap with React.createFactory
  • +
  • DEPRECATED use of key={null} to assign implicit keys
  • +
+

Bug Fixes #

+
    +
  • Better handling of events and updates in nested results, fixing value restoration in "layered" controlled components
  • +
  • Correctly treat event.getModifierState as case sensitive
  • +
  • Improved normalization of event.charCode
  • +
  • Better error stacks when involving autobound methods
  • +
  • Removed DevTools message when the DevTools are installed
  • +
  • Correctly detect required language features across browsers
  • +
  • Fixed support for some HTML attributes: + +
      +
    • list updates correctly now
    • +
    • scrollLeft, scrollTop removed, these should not be specified as props
    • +
  • +
  • Improved error messages
  • +
+

React With Addons #

New Features #

+
    +
  • React.addons.batchedUpdates added to API for hooking into update cycle
  • +
+

Breaking Changes #

+
    +
  • React.addons.update uses assign instead of copyProperties which does hasOwnProperty checks. Properties on prototypes will no longer be updated correctly.
  • +
+

Bug Fixes #

+
    +
  • Fixed some issues with CSS Transitions
  • +
+

JSX #

Breaking Changes #

+
    +
  • Enforced convention: lower case tag names are always treated as HTML tags, upper case tag names are always treated as composite components
  • +
  • JSX no longer transforms to simple function calls
  • +
+

New Features #

+
    +
  • @jsx React.DOM no longer required
  • +
  • spread ({...}) operator introduced to allow easier use of props
  • +
+

Bug Fixes #

+
    +
  • JSXTransformer: Make sourcemaps an option when using APIs directly (eg, for react-rails)
  • +
+ +
+ + + +
+ +
+ +

React.js Conf @@ -577,301 +719,6 @@ Minified build for production: - - -

- - Testing Flux Applications - -

- -

- September 24, 2014 - by - - - Bill Fisher - - - -

- -
- -
-

A more up-to-date version of this post is available as part of the Flux documentation.

- -

Flux is the application architecture that Facebook uses to build web applications with React. It's based on a unidirectional data flow. In previous blog posts and documentation articles, we've shown the basic structure and data flow, more closely examined the dispatcher and action creators, and shown how to put it all together with a tutorial. Now let's look at how to do formal unit testing of Flux applications with Jest, Facebook's auto-mocking testing framework.

-

Testing with Jest #

-

For a unit test to operate on a truly isolated unit of the application, we need to mock every module except the one we are testing. Jest makes the mocking of other parts of a Flux application trivial. To illustrate testing with Jest, we'll return to our example TodoMVC application.

- -

The first steps toward working with Jest are as follows:

- -
    -
  1. Get the module dependencies for the application installed by running npm install.
  2. -
  3. Create a directory __tests__/ with a test file, in this case TodoStore-test.js
  4. -
  5. Run npm install jest-cli —save-dev
  6. -
  7. Add the following to your package.json
  8. -
-
{
-  ...
-  "scripts": {
-    "test": "jest"
-  }
-  ...
-}
-
-

Now you're ready to run your tests from the command line with npm test.

- -

By default, all modules are mocked, so the only boilerplate we need in TodoStore-test.js is a declarative call to Jest's dontMock() method.

-
jest.dontMock('TodoStore');
-
-

This tells Jest to let TodoStore be a real object with real, live methods. Jest will mock all other objects involved with the test.

-

Testing Stores #

-

At Facebook, Flux stores often receive a great deal of formal unit test coverage, as this is where the application state and logic lives. Stores are arguably the most important place in a Flux application to provide coverage, but at first glance, it's not entirely obvious how to test them.

- -

By design, stores can't be modified from the outside. They have no setters. The only way new data can enter a store is through the callback it registers with the dispatcher.

- -

We therefore need to simulate the Flux data flow with this one weird trick.

-
var mockRegister = MyDispatcher.register;
-var mockRegisterInfo = mockRegister.mock;
-var callsToRegister = mockRegisterInfo.calls;
-var firstCall = callsToRegister[0];
-var firstArgument = firstCall[0];
-var callback = firstArgument;
-
-

We now have the store's registered callback, the sole mechanism by which data can enter the store.

- -

For folks new to Jest, or mocks in general, it might not be entirely obvious what is happening in that code block, so let's look at each part of it a bit more closely. We start out by looking at the register() method of our application's dispatcher — the method that the store uses to register its callback with the dispatcher. The dispatcher has been thoroughly mocked automatically by Jest, so we can get a reference to the mocked version of the register() method just as we would normally refer to that method in our production code. But we can get additional information about that method with the mock property of that method. We don't often think of methods having properties, but in Jest, this idea is vital. Every method of a mocked object has this property, and it allows us to examine how the method is being called during the test. A chronologically ordered list of calls to register() is available with the calls property of mock, and each of these calls has a list of the arguments that were used in each method call.

- -

So in this code, we are really saying, "Give me a reference to the first argument of the first call to MyDispatcher's register() method." That first argument is the store's callback, so now we have all we need to start testing. But first, we can save ourselves some semicolons and roll all of this into a single line:

-
callback = MyDispatcher.register.mock.calls[0][0];
-
-

We can invoke that callback whenever we like, independent of our application's dispatcher or action creators. We will, in fact, fake the behavior of the dispatcher and action creators by invoking the callback with an action that we'll create directly in our test.

-
var payload = {
-  source: 'VIEW_ACTION',
-  action: {
-    actionType: TodoConstants.TODO_CREATE,
-    text: 'foo'
-  }
-};
-callback(payload);
-var all = TodoStore.getAll();
-var keys = Object.keys(all);
-expect(all[keys[0]].text).toEqual('foo');
-

Putting it All Together #

-

The example Flux TodoMVC application has been updated with an example test for the TodoStore, but let's look at an abbreviated version of the entire test. The most important things to notice in this test are how we keep a reference to the store's registered callback in the closure of the test, and how we recreate the store before every test so that we clear the state of the store entirely.

-
jest.dontMock('../TodoStore');
-jest.dontMock('react/lib/merge');
-
-describe('TodoStore', function() {
-
-  var TodoConstants = require('../../constants/TodoConstants');
-
-  // mock actions inside dispatch payloads
-  var actionTodoCreate = {
-    source: 'VIEW_ACTION',
-    action: {
-      actionType: TodoConstants.TODO_CREATE,
-      text: 'foo'
-    }
-  };
-  var actionTodoDestroy = {
-    source: 'VIEW_ACTION',
-    action: {
-      actionType: TodoConstants.TODO_DESTROY,
-      id: 'replace me in test'
-    }
-  };
-
-  var AppDispatcher;
-  var TodoStore;
-  var callback;
-
-  beforeEach(function() {
-    AppDispatcher = require('../../dispatcher/AppDispatcher');
-    TodoStore = require('../TodoStore');
-    callback = AppDispatcher.register.mock.calls[0][0];
-  });
-
-  it('registers a callback with the dispatcher', function() {
-    expect(AppDispatcher.register.mock.calls.length).toBe(1);
-  });
-
-  it('initializes with no to-do items', function() {
-    var all = TodoStore.getAll();
-    expect(all).toEqual({});
-  });
-
-  it('creates a to-do item', function() {
-    callback(actionTodoCreate);
-    var all = TodoStore.getAll();
-    var keys = Object.keys(all);
-    expect(keys.length).toBe(1);
-    expect(all[keys[0]].text).toEqual('foo');
-  });
-
-  it('destroys a to-do item', function() {
-    callback(actionTodoCreate);
-    var all = TodoStore.getAll();
-    var keys = Object.keys(all);
-    expect(keys.length).toBe(1);
-    actionTodoDestroy.action.id = keys[0];
-    callback(actionTodoDestroy);
-    expect(all[keys[0]]).toBeUndefined();
-  });
-
-});
-
-

You can take a look at all this code in the TodoStore's tests on GitHub as well.

-

Mocking Data Derived from Other Stores #

-

Sometimes our stores rely on data from other stores. Because all of our modules are mocked, we'll need to simulate the data that comes from the other store. We can do this by retrieving the mock function and adding a custom return value to it.

-
var MyOtherStore = require('../MyOtherStore');
-MyOtherStore.getState.mockReturnValue({
-  '123': {
-    id: '123',
-    text: 'foo'
-  },
-  '456': {
-    id: '456',
-    text: 'bar'
-  }
-});
-
-

Now we have a collection of objects that will come back from MyOtherStore whenever we call MyOtherStore.getState() in our tests. Any application state can be simulated with a combination of these custom return values and the previously shown technique of working with the store's registered callback.

- -

A brief example of this technique is up on GitHub within the Flux Chat example's UnreadThreadStore-test.js.

- -

For more information about the mock property of mocked methods or Jest's ability to provide custom mock values, see Jest's documentation on mock functions.

-

Moving Logic from React to Stores #

-

What often starts as a little piece of seemingly benign logic in our React components often presents a problem while creating unit tests. We want to be able to write tests that read like a specification for our application's behavior, and when application logic slips into our view layer, this becomes more difficult.

- -

For example, when a user has marked each of their to-do items as complete, the TodoMVC specification dictates that we should also change the status of the "Mark all as complete" checkbox automatically. To create that logic, we might be tempted to write code like this in our MainSection's render() method:

-
var allTodos = this.props.allTodos;
-var allChecked = true;
-for (var id in allTodos) {
-  if (!allTodos[id].complete) {
-    allChecked = false;
-    break;
-  }
-}
-...
-
-return (
-  <section id="main">
-  <input
-    id="toggle-all"
-    type="checkbox"
-    checked={allChecked ? 'checked' : ''}
-  />
-  ...
-  </section>
-);
-
-

While this seems like an easy, normal thing to do, this is an example of application logic slipping into the views, and it can't be described in our spec-style TodoStore test. Let's take that logic and move it to the store. First, we'll create a public method on the store that will encapsulate that logic:

-
areAllComplete: function() {
-  for (var id in _todos) {
-    if (!_todos[id].complete) {
-      return false;
-    }
-  }
-  return true;
-},
-
-

Now we have the application logic where it belongs, and we can write the following test:

-
it('determines whether all to-do items are complete', function() {
-  var i = 0;
-  for (; i < 3; i++) {
-    callback(mockTodoCreate);
-  }
-  expect(TodoStore.areAllComplete()).toBe(false);
-
-  var all = TodoStore.getAll();
-  for (key in all) {
-    callback({
-      source: 'VIEW_ACTION',
-      action: {
-        actionType: TodoConstants.TODO_COMPLETE,
-        id: key
-      }
-    });
-  }
-  expect(TodoStore.areAllComplete()).toBe(true);
-
-  callback({
-    source: 'VIEW_ACTION',
-    action: {
-      actionType: TodoConstants.TODO_UNDO_COMPLETE,
-      id: key
-    }
-  });
-  expect(TodoStore.areAllComplete()).toBe(false);
-});
-
-

Finally, we revise our view layer. We'll call for that data in the controller-view, TodoApp.js, and pass it down to the MainSection component.

-
function getTodoState() {
-  return {
-    allTodos: TodoStore.getAll(),
-    areAllComplete: TodoStore.areAllComplete()
-  };
-}
-
-var TodoApp = React.createClass({
-...
-
-  /**
-   * @return {object}
-   */
-  render: function() {
-    return (
-      ...
-      <MainSection
-        allTodos={this.state.allTodos}
-        areAllComplete={this.state.areAllComplete}
-      />
-      ...
-    );
-  },
-
-  /**
-   * Event handler for 'change' events coming from the TodoStore
-   */
-  _onChange: function() {
-    this.setState(getTodoState());
-  }
-
-});
-
-

And then we'll utilize that property for the rendering of the checkbox.

-
render: function() {
-  ...
-
-  return (
-    <section id="main">
-    <input
-      id="toggle-all"
-      type="checkbox"
-      checked={this.props.areAllComplete ? 'checked' : ''}
-    />
-    ...
-    </section>
-  );
-},
-
-

To learn how to test React components themselves, check out the Jest tutorial for React and the ReactTestUtils documentation.

-

Further Reading #

- - -
- - -

diff --git a/docs/component-specs.html b/docs/component-specs.html index 6bfb7c3dd7..26ff2d8225 100644 --- a/docs/component-specs.html +++ b/docs/component-specs.html @@ -487,6 +487,8 @@

Note:

+

One common mistake is for code executed during this lifecycle method to assume that props have changed. To understand why this is invalid, read A implies B does not imply B implies A

+

There is no analogous method componentWillReceiveState. An incoming prop transition may cause a state change, but the opposite is not true. If you need to perform operations in response to a state change, use componentWillUpdate.

Updating: shouldComponentUpdate #

boolean shouldComponentUpdate(
diff --git a/docs/forms.html b/docs/forms.html
index 4f806f1a6a..b03843557a 100644
--- a/docs/forms.html
+++ b/docs/forms.html
@@ -481,7 +481,7 @@
 

This example will function much like the Uncontrolled Components example above.

-

Likewise, <input> supports defaultChecked and <select> supports defaultValue.

+

Likewise, <input type="checkbox"> and <input type="radio"> support defaultChecked, and <select> supports defaultValue.

Note:

diff --git a/docs/reconciliation.html b/docs/reconciliation.html index c51c1af4f6..c8c2eb9703 100644 --- a/docs/reconciliation.html +++ b/docs/reconciliation.html @@ -415,7 +415,7 @@

Motivation #

Generating the minimum number of operations to transform one tree into another is a complex and well-studied problem. The state of the art algorithms have a complexity in the order of O(n3) where n is the number of nodes in the tree.

-

This means that displaying 1000 nodes would require in the order of one billion comparisons. This is far too expensive for our use case. To put this number in perspective, CPUs nowadays execute roughly 3 billion instruction per second. So even with the most performant implementation, we wouldn't be able to compute that diff in less than a second.

+

This means that displaying 1000 nodes would require in the order of one billion comparisons. This is far too expensive for our use case. To put this number in perspective, CPUs nowadays execute roughly 3 billion instructions per second. So even with the most performant implementation, we wouldn't be able to compute that diff in less than a second.

Since an optimal algorithm is not tractable, we implement a non-optimal O(n) algorithm using heuristics based on two assumptions:

diff --git a/docs/test-utils.html b/docs/test-utils.html index d22a5c41f4..822ae00cd8 100644 --- a/docs/test-utils.html +++ b/docs/test-utils.html @@ -539,7 +539,8 @@ </div>

Then you can assert:

-
result = renderer.getRenderOutput();
+
var renderer = ReactTestUtils.createRenderer();
+result = renderer.getRenderOutput();
 expect(result.type).toBe('div');
 expect(result.props.children).toEqual([
   <span className="heading">Title</span>,
diff --git a/docs/thinking-in-react-ko-KR.html b/docs/thinking-in-react-ko-KR.html
index 777aa328f3..4d8f326cbf 100644
--- a/docs/thinking-in-react-ko-KR.html
+++ b/docs/thinking-in-react-ko-KR.html
@@ -467,7 +467,7 @@
 
 
 

2단계: 정적 버전을 만드세요. #

- +

계층구조의 컴포넌트들을 가지고 있으니, 이젠 애플리케이션을 구현할 시간입니다. 가장 쉬운 방법은 상호작용을 하지 않는 채로 자료 모델을 이용해 UI를 그리는 것입니다. 정적 버전을 만드는 데에는 적은 생각과 많은 노동이 필요하고, 상호작용을 추가하는 데에는 많은 생각과 적은 노동이 필요하기 때문에 둘을 분리하는 것이 가장 좋습니다. 왜 그런지 봅시다.

@@ -511,7 +511,7 @@
  • 체크박스의 값
  • 4단계: 어디서 state가 유지되어야 하는지 확인하세요. #

    - +

    이제 최소한의 state가 무엇인지 알아냈습니다. 다음은, 어떤 컴포넌트가 이 state를 변형하거나 만들어낼지 알아내야 합니다.

    @@ -538,7 +538,7 @@

    이제 어떻게 애플리케이션이 동작하는지 볼 수 있습니다: filterText"ball"로 설정하고 업데이트합니다. 자료 테이블이 제대로 업데이트 되는 것을 볼 수 있을 겁니다.

    5단계: 반대방향 자료 흐름을 추가하세요. #

    - +

    앞서 우리는 계층적으로 아랫방향 흐름의 props, state전달로 잘 동작하는 애플리케이션을 만들었습니다. 이제 다른방향의 자료 흐름을 지원할 시간입니다: form 컴포넌트들은 FilterableProductTable의 state를 업데이트할 필요성이 있죠.

    diff --git a/docs/thinking-in-react.html b/docs/thinking-in-react.html index 7c2aa154ac..af1585e83d 100644 --- a/docs/thinking-in-react.html +++ b/docs/thinking-in-react.html @@ -467,7 +467,7 @@

    Step 2: Build a static version in React #

    - +

    Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why.

    @@ -511,7 +511,7 @@
  • The value of the checkbox
  • Step 4: Identify where your state should live #

    - +

    OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or owns, this state.

    @@ -538,7 +538,7 @@

    You can start seeing how your application will behave: set filterText to "ball" and refresh your app. You'll see that the data table is updated correctly.

    Step 5: Add inverse data flow #

    - +

    So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in FilterableProductTable.

    diff --git a/docs/thinking-in-react.it-IT.html b/docs/thinking-in-react.it-IT.html index dde298f96b..75692ebb80 100644 --- a/docs/thinking-in-react.it-IT.html +++ b/docs/thinking-in-react.it-IT.html @@ -467,7 +467,7 @@

    Passo 2: Costruisci una versione statica in React #

    - +

    Adesso che hai la tua gerarchia di componenti, è venuto il momento di implementare la tua applicazione. La maniera più semplice è costruire una versione che prende il tuo modello di dati e visualizza la UI ma non è interattiva. È buona norma disaccoppiare questi processi perché costruire una versione statica richiede la scrittura di parecchio codice e poco pensare, mentre aggiungere l'interattività richiede un parecchio pensare ma non un granché di scrittura. Vedremo perché.

    @@ -511,7 +511,7 @@
  • Il valore del checkbox
  • Passo 4: Identifica dove debba risiedere il tuo stato #

    - +

    OK, abbiamo dunque identificato quale sia l'insieme minimo dello stato dell'applicazione. Successivamente, dobbiamo identificare quale componente muta, o possiede, questo stato.

    @@ -538,7 +538,7 @@

    Puoi cominciare a vedere come si comporterà la tua applicazione: imposta filterText a "ball" e aggiorna la tua applicazione. Vedrai che la tabella dei dati è correttamente aggiornata.

    Passo 5: Aggiungi il flusso dati inverso #

    - +

    Finora abbiamo costruito un'applicazione che visualizza correttamente come una funzione di proprietà e stato che fluiscono verso il basso della gerarchia. Adesso è il momento di supportare il flusso dei dati nella direzione opposta: i componenti del modulo in profondità nella gerarchia devono aggiornare lo stato in FilterableProductTable.

    diff --git a/docs/thinking-in-react.zh-CN.html b/docs/thinking-in-react.zh-CN.html index 03648583b0..53a2f00cf6 100644 --- a/docs/thinking-in-react.zh-CN.html +++ b/docs/thinking-in-react.zh-CN.html @@ -413,11 +413,11 @@

    by Pete Hunt

    -

    在我看来,React 是构建大型,快速 web app 的首选方式。它已经在 Facebook 和 Instagram 被我们有了广泛的应用。

    +

    在我看来,React 是构建大型,快速 Web app 的首选方式。它已经在 Facebook 和 Instagram 被我们有了广泛的应用。

    -

    React许多优秀的部分之一是它如何使你随着构建 app 来思考 app。在本文里,我将带领你学习一个用 React 构建可搜索的数据表的思考过程。

    +

    React 许多优秀的部分之一,是它使得你在构建 app 的过程中不断思考。在本文里,我将带你经历一次使用 React 构建可搜索的商品数据表的思考过程。

    从模型(mock)开始 #

    -

    想象我们已经有个一个 JSON API 和一个来自设计师的模型。我们的设计师似乎不是很好因为模型看起来像是这样:

    +

    想象我们已经有个一个 JSON API 和一个来自设计师的模型。我们的设计师显然做得不够好,因为模型看起来像这样:

    Mockup

    @@ -431,27 +431,27 @@ {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ];

    第一步:把UI拆分为一个组件的层级 #

    -

    首先你想要做的是在模型里的每一个组建周围绘制边框并给他们命名。如果你和设计师一起工作,他们应该已经完成这步了,所以去和他们谈谈!他们的photoshop图层名也许最终会成为你的React组件名。

    +

    首先你想要做的,是在模型里的每一个组件周围绘制边框,并给它们命名。如果你和设计师一起工作,他们应该已经完成这步了,所以去和他们谈谈!他们的 Photoshop 图层名也许最终会成为你的 React 组件名。

    -

    但是你如何知道什么东西应该是独立的组件?只需使用你决定是否创建一个函数或者对象的相同技术。这样一种技术是single responsibility principle,即是,一个组件在理想情况下只做一件事情。如果它最终变大,它就应该被分解为更小的组件。

    +

    但是你如何知道什么东西应该是独立的组件?只需在你创建一个函数或者对象时,根据是否使用过相同技术来做决定。一种这样的技术是单一功能原则(single responsibility principle),也就是一个组件在理想情况下只做一件事情。如果它最终增长了,它就应该被分解为更小的组件。

    -

    既然你频繁显示一个JSON的数据模型给用户,你会发现,如果你的模型构建正确,你的UI(因此也有你的组件结构)就将映射良好.那是因为UI和数据模型趋向于附着于相同的 信息架构,这意味着把你的 UI 分离为组件的工作通常是简单的,只需把他拆成精确对应代表你的数据模型的每一块的组件.

    +

    既然你频繁显示一个 JSON 的数据模型给用户,你会发现,如果你的模型构建正确,你的 UI(因此也有你的组件结构)就将映射良好。那是因为 UI 和数据模型趋向附着于相同的 信息架构,这意味着,把你的 UI 分离为组件的工作通常是琐碎的,只需把 UI 拆分成能准确对应数据模型的每块组件。

    Component diagram

    -

    在这里你会看到,在我们简单的APP里有五个组件.我用斜体表示每个组件的数据.

    +

    在这里你会看到,在我们的简单 APP 里有五个组件。我用斜体表示每个组件的数据。

      -
    1. FilterableProductTable (orange): 包含示例的整体
    2. -
    3. SearchBar (blue): 接受所有 用户输入
    4. -
    5. ProductTable (green): 基于 用户输入 显示和过滤 数据集合(data collection)
    6. -
    7. ProductCategoryRow (turquoise): 为每个 分类 显示一个列表头
    8. -
    9. ProductRow (red): 为每个 产品 显示一个行
    10. +
    11. FilterableProductTable (橙色): 包含示例的整体
    12. +
    13. SearchBar (蓝色): 接收所有 用户输入
    14. +
    15. ProductTable (绿色): 基于 用户输入 显示和过滤 数据集合(data collection)
    16. +
    17. ProductCategoryRow (蓝绿色): 为每个 分类 显示一个列表头
    18. +
    19. ProductRow (红色): 为每个 商品 显示一行
    -

    如果你看着 ProductTable,你会看到表的头(包含了 "Name" 和 "Price" 标签) 不是独立的组件.这是一个个人喜好问题,并且无论哪种方式都有争论.对于这个例子,我把它留做 ProductTable 的一部分,因为它是 data collection渲染的一部分,而 data collection渲染是 ProductTable 的职责.然而,当列表头增长到复杂的时候(例如 如果我们添加排序的功能性),那么无疑的使它成为独立的 ProductTableHeader 组件是有意义的.

    +

    如果你看着 ProductTable,你会看到表头(包含了 "Name" 和 "Price" 标签) 不是独立的组件。这是一个个人喜好问题,并且无论采用哪种方式都有争论。对于这个例子,我把它留做 ProductTable 的一部分,因为它是 data collection渲染的一部分,而 data collection 渲染是 ProductTable 的职责。然而,当列表头增长到复杂的时候(例如 如果我们添加排序功能),那么使它成为独立的 ProductTableHeader 组件无疑是有意义的。

    -

    既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中.这很容易. 在模型中出现在其他组件中的组件 同样应该在层级中表现为一个子级:

    +

    既然现在我们已经识别出了我们模型中的组件,让我们把他们安排到一个层级中。这很容易。在模型中,出现在一个组件里面的另一组件 ,应该在层级中表现为一种子级关系:

    • FilterableProductTable @@ -466,43 +466,43 @@
    -

    Step 2: 用React创建一个静态版本 #

    - +

    第二步:用React创建一个静态版本 #

    + -

    既然你已经有了你的组件层级,时候实现你的app了.简单的方式是构建一个版本,它采取你的数据模型并渲染UI但是没有互动性.最好是分离这些过程,因为构建一个静态版本需要无脑的打很多字,然而添加互动性需要很多思考但不需要打太多字.我们会看到是为什么:

    +

    既然你已经有了你的组件层级,是时候实现你的app了。简单的方式是构建一个版本,它取走你的数据模型并渲染UI,除了没有互动性。这是将过程解耦的最好办法,因为构建一个静态版本需要不假思索地写很多代码,而添加互动性需要很多思考但不需要太多代码。之后我们将会看到原因。

    -

    要构建一个渲染你的数据模型的 app 的静态版本,你会想构建一个重用其他组件并利用 props 传递数据的组件. props 是一种从父级传递数据到子级的方式.如果你对 state 的观念很熟悉, 绝不要用state 来构建这个静态版本.State 仅仅是为互动预留的,即,随时间变化的数据. 因为这是一个静态版本的app,你不需要它.

    +

    要构建一个静态版本 app 来渲染你的数据模型,你将会想到构建一个重用其它组件并利用 props 传递数据的组件。props 是一种从父级传递数据到子级的方式。如果你对 state 的观念很熟悉,绝不要用state 来构建这个静态版本。State 仅仅是为互动性,也就是随时间变化的数据所预留的。由于这是一个静态版本,你还不需要用到它。

    -

    你可以自顶向下或自底向上的构建.也就是说,你可以既从较高的层级(如 从 FilterableProductTable 开始) 也可以从较低的层级(ProductRow)开始构建组件. 在较简单的例子里,通常自顶向下要容易一些,然而在更大的项目上 自底向上更容易,并且伴随着构建写测试较容易.

    +

    你可以自顶向下或自底向上的构建。也就是说,你可以既从较高的层级(比如从 FilterableProductTable 开始)也可以从较低的层级(ProductRow)开始构建组件。在较简单的例子里,通常自顶向下要容易一些,然而在更大的项目上,自底向上地构建更容易,并且更方便伴随着构建写测试。

    -

    在这一步的最后,你会有一个渲染你数据模型的可重用的组件库. 这些组件将只含有 render() 方法因为这是一个你的app的静态版本. 在层级顶端的组件 (FilterableProductTable) 将会接受你的数据模型作为一个prop.如果你对你的底层数据模型做了变化并且再次调用 React.render() ,UI将会更新.很容易看到你的UI是如何更新以及哪里来作出变动,因为这里没有任何复杂的事情发生. React的 单向数据流 (也被称为 单向绑定 )保持了每个东西模块化和快速.

    +

    在这一步的最后,你会获得一个渲染数据模型的可重用组件库。这些组件只有 render() 方法,因为这是一个静态版本。在层级顶端的组件 (FilterableProductTable) 将会接受你的数据模型,并将其作为一个prop。如果你改变了底层数据模型,并且再次调用 React.render() ,UI 将会更新。你可以很容易地看到 UI 是如何更新的,以及哪里变动了,因为这没什么复杂的。React的 单向数据流 (也被称为 单向绑定)使一切保持了模块化和快速。

    -

    如果你执行这步需要帮助,请参考 React docs .

    +

    如果你在执行这步时需要帮助,请参阅 React 文档

    小插曲: props vs state #

    -

    在React里有两种数据 "模型":props和state.明白这二者之间的区别是很重要的;如果你不是很确定不同是什么,请概览React官方文档

    -

    第三步:确定最小(但完备)的 UI state 的表达 #

    -

    要让你的UI互动,你需要能够触发变化到你的底层数据模型上.React用 state 来让此变得容易.

    +

    在React里有两种数据 "模型": props 和 state。明白这二者之间的区别是很重要的;如果你不是很确定它们之间的区别,请概览React官方文档

    +

    第三步:确定最小(但完备)的 UI state 表达 #

    +

    要让你的 UI 互动,你需要做到触发底层数据模型发生变化。React用 state 来让此变得容易。

    -

    要正确的构建你的app,你首先需要思考你的app需要的可变state的最小组. 这里的关键是 DRY: Don't Repeat Yourself(不要重复自己).想出哪些是你的应用需要的绝对最小 state 表达,并按需计算其他任何数据.例如,如果你要构建一个 TODO list,只要保持一个 TODO 项的数组;不要为了计数保持一个单独的 state 变量.作为替代,当你想渲染 TODO 数量时,简单的采用TODO项目数组的长度.

    +

    要正确的构建你的 app,你首先需要思考你的 app 需要的可变 state 的最小组。这里的关键是 DRY 原则:Don't Repeat Yourself(不要重复自己)。想出哪些是你的应用需要的绝对最小 state 表达,并按需计算其他任何数据。例如,如果你要构建一个 TODO list,只要保持一个 TODO 项的数组;不要为了计数保持一个单独的 state 变量。当你想渲染 TODO 的计数时,简单的采用 TODO 项目的数组长度作为替代。

    -

    考虑我们例子应用中数据的所有块.我们有:

    +

    考虑我们示例应用中的数据所有块,包括:

      -
    • 原始的产品列表
    • +
    • 原始的商品列表
    • 用户输入的搜索文本
    • -
    • checkbox的值
    • -
    • 产品的滤过的列表
    • +
    • 复选框的值
    • +
    • 商品的过滤列表
    -

    让我们遍历每一个并指出哪一个是state.简单的问三个关于每个数据块的问题:

    +

    让我们逐个检查出哪一个是state,只需要简单地问以下三个问题:

      -
    1. 它是通过props从父级传递来的吗?如果是,它可能不是state.
    2. -
    3. 它随时间变化吗?如果不是,它可能不是state.
    4. -
    5. 你能基于其他任何组件里的 state 或者 props 计算出它吗?如果是,它可能不是state.
    6. +
    7. 它是通过props从父级传递来的吗?如果是,它可能不是 state。
    8. +
    9. 它随时间变化吗?如果不是,它可能不是 state。
    10. +
    11. 你能基于其他任何组件里的 state 或者 props 计算出它吗?如果是,它可能不是state.
    -

    原始的产品列表被以 props 传入,所以它不是 state. 搜索文本和 checkbox 看起来是state 因为他们随时间变化并且不能从任何东西计算出.最后,产品滤过的列表不是state因为它可以联合原始列表与搜索文本及 checkbox 的值计算出.

    +

    原始的商品列表以 props 传入,所以它不是 state。搜索文本和复选框看起来是 state,因为他们随时间变化并且不能从任何东西计算出。最后,过滤出的商品列表不是 state,因为它可以通过原始列表与搜索文本及复选框的值组合计算得出。

    所以最后,我们的 state 是:

    @@ -510,47 +510,47 @@
  • 用户输入的搜索文本
  • checkbox 的值
  • -

    第四步:确定你的 state 应该存在于哪里 #

    - +

    第四步:确定你的 state 应该存在于哪里 #

    + -

    好,我们已经确定了app state 的最小组是什么.接下来,我们需要确定哪个组件变动,或者 拥有,这 个state.

    +

    OK,我们已经确定好应用的最小 state 集合是什么。接下来,我们需要确定哪个组件可以改变,或者 拥有 这个state.

    -

    记住:React都是关于单向数据流下组件层级的.可能不能立刻明白哪些组件应该拥有哪些 state. 这常常对于新手在理解上是最具挑战的一部分, 所以跟着这几步来弄明白它:

    +

    记住:React 总是在组件层级中单向数据流动的。可能不能立刻明白哪些组件应该拥有哪些 state。 这对于新手在理解上经常是最具挑战的一部分, 所以跟着这几步来弄明白它:

    -

    对于你的应用里每一个数据块:

    +

    对于你的应用里每一个数据块:

      -
    • 基于 state 确定每个绘制某些东西的组件
    • -
    • 找到一个共同拥有者的组件(在层级中所有组件之上需要这个state的单个组件)
    • -
    • 要么是共同拥有者,要么是其他在层级里更高级的组件应该拥有这个state
    • -
    • 如果你不能找到一个组件,它拥有这个state有意义,创建一个新的组件简单的为了持有此state,并把它在层级里添加比共同拥有者组件更高的层级上.
    • +
    • 确定哪些组件要基于 state 来渲染内容。
    • +
    • 找到一个共同的拥有者组件(在所有需要这个state组件的层次之上,找出共有的单一组件)。
    • +
    • 要么是共同拥有者,要么是其他在层级里更高级的组件应该拥有这个state。
    • +
    • 如果你不能找到一个组件让其可以有意义地拥有这个 state,可以简单地创建一个新的组件 hold 住这个state,并把它添加到比共同拥有者组件更高的层级上。
    -

    让我们过一遍这个用于我们应用的策略:

    +

    让我们使用这个策略浏览一遍我们的应用:

      -
    • ProductTable 需要基于 state 过滤产品列表,SearchBar 需要显示搜索文本和选择状态.
    • -
    • 共同拥有者组件是FilterableProductTable .
    • -
    • 对于过滤文本和选择值存在于 FilterableProductTable 观念上是有意义的.
    • +
    • ProductTable 需要基于 state 过滤产品列表,SearchBar 需要显示搜索文本和选择状态。
    • +
    • 共同拥有者组件是 FilterableProductTable
    • +
    • 对于过滤文本和选择框值存在于 FilterableProductTable,从概念上讲是有意义的。
    -

    酷,我们已经决定了我们的state存在于 FilterableProductTable .首先,添加一个 getInitialState() 方法到 FilterableProductTable ,返回 {filterText: '', inStockOnly: false} 来反映你的应用的初始状态. 然后,传递filterTextinStockOnlyProductTableSearchBar 作为prop.最后,使用这些prop来过滤 ProductTable 中的行和设置SearchBar的表单项的值.

    +

    酷,我们已经决定了我们的 state 存在于 FilterableProductTable。首先,添加一个 getInitialState() 方法到 FilterableProductTable,返回 {filterText: '', inStockOnly: false} 来反映应用的初始状态。然后,传递filterTextinStockOnlyProductTableSearchBar 作为 prop。最后,使用这些 prop 来过滤 ProductTable 中的行和设置 SearchBar 的表单项的值。

    -

    你可以开始看看你的应用将有怎样的行为: 设置 filterText"ball" 并刷新你的app.你将看到数据表被正确更新了.

    -

    第五步:添加反向数据流 #

    - +

    你可以开始看看你的应用将有怎样的行为了: 设置 filterText"ball" 并刷新你的 app。你将可以看到数据表被正确地更新。

    +

    第五步:添加反向数据流 #

    + -

    到目前为止,我们已经构建了一个应用, 它以props 和 state 沿着层级向下流动的功能正确渲染。现在是时候支持数据的另一种流动了:在层级深处的表单组件需要更新 FilterableProductTable 里的state.

    +

    到目前为止,我们已经构建了一个应用, 它以 props 和 state 沿着层级向下流动的功能正确渲染。现在是时候支持另一种数据流动了:在层级深处的表单组件需要更新 FilterableProductTable 里的 state。

    -

    React 让数据显式流动,使理解你的应用如何工作变得简单,但是相对于传统的双向数据绑定,确实需要打多一些的字。 React 提供了一个叫做 ReactLink 的插件来使这种模式和双向数据绑定一样方便,但是考虑到这篇文章的目的,我们将会保持所有东西都直截了当。

    +

    React 让数据显式流动,使你理解应用如何工作变得简单,但是相对于传统的双向数据绑定,确实需要多打一些字。React 提供了一个叫做 ReactLink 的插件来使这种模式和双向数据绑定一样方便,但是考虑到这篇文章的目的,我们将会保持所有东西都直截了当。

    -

    如果你尝试在当前版本的示例中输入或者选中复选框,你会发现 React 忽略了你的输入。这是有意的,因为已经设置了 inputvalue prop 总是与 FilterableProductTable 传递过来的 state 一致。

    +

    如果你尝试在当前版本的示例中输入或者选中复选框,你会发现 React 忽略了你的输入。这是有意的,因为我们已经设置了 inputvalue prop 值总是与 FilterableProductTable 传递过来的 state 一致。

    -

    让我们思考下我们希望发生什么。我们想确保每当用户改变了表单,我们就更新 state 来反映用户的输入。由于组件应该只更新自己拥有的 state , FilterableProductTable 将会传递一个回调函数给 SearchBar ,此函数每当 state 应被改变时就会击发。我们可以使用 input 的 onChange 事件来接受它的通知。 FilterableProductTable 传递的回调函数将会调用 setState() ,然后应用将会被更新。

    +

    让我们思考下希望发生什么。我们想确保每当用户改变表单,就通过更新 state 来反映用户的输入。由于组件应该只更新自己拥有的 state , FilterableProductTable 将会传递一个回调函数给 SearchBar ,每当 state 应被更新时回调函数就会被调用。我们可以使用 input 的 onChange 事件来接受它的通知。 FilterableProductTable 传递的回调函数将会调用 setState() ,然后应用将会被更新。

    -

    虽然这听起来复杂,但是实际上只是数行代码。并且数据在应用中从始至终如何流动是非常明确的。

    -

    好了,就是这样 #

    -

    希望,这给了你一个怎样思考用React构建组件和应用的概念。虽然可能比你通常要输入更多的代码,记住,读代码的时间远比写代码的时间多,并且阅读这种模块化的,显式的代码是极端容易的。当你开始构建大型组件库时,你会非常感激这种清晰性和模块化,并且随着代码的重用,你的代码行数将会开始缩减. :)。

    +

    虽然这听起来复杂,但是实际上只是数行代码。并且这明确显示出了数据在应用中从始至终是如何流动的。

    +

    好了,就是这样 #

    +

    希望这给了你一个怎样思考用React构建组件和应用的概念。虽然可能比你过往的习惯要多敲一点代码,但记住,读代码的时间远比写代码的时间多,并且阅读这种模块化的、显式的代码是极为容易的。当你开始构建大型组件库时,你会非常感激这种清晰性和模块化,并且随着代码的重用,你的代码行数将会开始缩减。:)

    diff --git a/feed.xml b/feed.xml index c7ac9fa551..4dea574af0 100644 --- a/feed.xml +++ b/feed.xml @@ -6,6 +6,64 @@ https://facebook.github.io/react + + (A => B) !=> (B => A) + <p>The documentation for <code>componentWillReceiveProps</code> states that <code>componentWillReceiveProps</code> will be invoked when the props change as the result of a rerender. Some people assume this means &quot;if <code>componentWillReceiveProps</code> is called, then the props must have changed&quot;, but that conclusion is logically incorrect.</p> + +<p>The guiding principle is one of my favorites from formal logic/mathematics:</p> + +<blockquote> +<p>A implies B does not imply B implies A</p> +</blockquote> + +<p>Example: &quot;If I eat moldy food, then I will get sick&quot; does not imply &quot;if I am sick, then I must have eaten moldy food&quot;. There are many other reasons I could be feeling sick. For instance, maybe the flu is circulating around the office. Similarly, there are many reasons that <code>componentWillReceiveProps</code> might get called, even if the props didn’t change.</p> + +<p>If you don’t believe me, call <code>ReactDOM.render()</code> three times with the exact same props, and try to predict the number of times <code>componentWillReceiveProps</code> will get called:</p> +<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="kr">class</span> <span class="nx">Component</span> <span class="kr">extends</span> <span class="nx">React</span><span class="p">.</span><span class="nx">Component</span> <span class="p">{</span> + <span class="nx">componentWillReceiveProps</span><span class="p">(</span><span class="nx">nextProps</span><span class="p">)</span> <span class="p">{</span> + <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;componentWillReceiveProps&#39;</span><span class="p">,</span> <span class="nx">nextProps</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">bar</span><span class="p">);</span> + <span class="p">}</span> + <span class="nx">render</span><span class="p">()</span> <span class="p">{</span> + <span class="k">return</span> <span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span><span class="nx">Bar</span> <span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">bar</span><span class="p">}</span><span class="o">!&lt;</span><span class="err">/div&gt;;</span> + <span class="p">}</span> +<span class="p">}</span> + +<span class="kd">var</span> <span class="nx">container</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s1">&#39;container&#39;</span><span class="p">);</span> + +<span class="kd">var</span> <span class="nx">mydata</span> <span class="o">=</span> <span class="p">{</span><span class="nx">bar</span><span class="o">:</span> <span class="s1">&#39;drinks&#39;</span><span class="p">};</span> +<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Component</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">mydata</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> +<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Component</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">mydata</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> +<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Component</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">mydata</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> +</code></pre></div> +<p>In this case, the answer is &quot;2&quot;. React calls <code>componentWillReceiveProps</code> twice (once for each of the two updates). Both times, the value of &quot;drinks&quot; is printed (ie. the props didn’t change).</p> + +<p>To understand why, we need to think about what <em>could</em> have happened. The data <em>could</em> have changed between the initial render and the two subsequent updates, if the code had performed a mutation like this:</p> +<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="kd">var</span> <span class="nx">mydata</span> <span class="o">=</span> <span class="p">{</span><span class="nx">bar</span><span class="o">:</span> <span class="s1">&#39;drinks&#39;</span><span class="p">};</span> +<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Component</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">mydata</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> +<span class="nx">mydata</span><span class="p">.</span><span class="nx">bar</span> <span class="o">=</span> <span class="s1">&#39;food&#39;</span> +<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Component</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">mydata</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> +<span class="nx">mydata</span><span class="p">.</span><span class="nx">bar</span> <span class="o">=</span> <span class="s1">&#39;noise&#39;</span> +<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">Component</span> <span class="nx">data</span><span class="o">=</span><span class="p">{</span><span class="nx">mydata</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> +</code></pre></div> +<p>React has no way of knowing that the data didn’t change. Therefore, React needs to call <code>componentWillReceiveProps</code>, because the component needs to be notified of the new props (even if the new props happen to be the same as the old props).</p> + +<p>You might think that React could just use smarter checks for equality, but there are some issues with this idea:</p> + +<ul> +<li>The old <code>mydata</code> and the new <code>mydata</code> are actually the same physical object (only the object’s internal value changed). Since the references are triple-equals-equal, doing an equality check doesn’t tell us if the value has changed. The only possible solution would be to have created a deep copy of the data, and then later do a deep comparison - but this can be prohibitively expensive for large data structures (especially ones with cycles).</li> +<li>The <code>mydata</code> object might contain references to functions which have captured variables within closures. There is no way for React to peek into these closures, and thus no way for React to copy them and/or verify equality.</li> +<li>The <code>mydata</code> object might contain references to objects which are re-instantiated during the parent&#39;s render (ie. not triple-equals-equal) but are conceptually equal (ie. same keys and same values). A deep-compare (expensive) could detect this, except that functions present a problem again because there is no reliable way to compare two functions to see if they are semantically equivalent.</li> +</ul> + +<p>Given the language constraints, it is sometimes impossible for us to achieve meaningful equality semantics. In such cases, React will call <code>componentWillReceiveProps</code> (even though the props might not have changed) so the component has an opportunity to examine the new props and act accordingly.</p> + +<p>As a result, your implementation of <code>componentWillReceiveProps</code> MUST NOT assume that your props have changed. If you want an operation (such as a network request) to occur only when props have changed, your <code>componentWillReceiveProps</code> code needs to check to see if the props actually changed.</p> + + 2016-01-08T00:00:00-08:00 + https://facebook.github.io/react/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html + https://facebook.github.io/react/blog/2016/01/08/A-implies-B-does-not-imply-B-implies-A.html + + React v0.14.4 <p>Happy December! We have a minor point release today. It has just a few small bug fixes.</p> @@ -886,120 +944,5 @@ Minified build for production: <a href="https://fb.me/react-dom-0.14.0.m https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html - - ReactDOM.render and the Top Level React API - <p>When you&#39;re in React&#39;s world you are just building components that fit into other components. Everything is a component. Unfortunately not everything around you is built using React. At the root of your tree you still have to write some plumbing code to connect the outer world into React.</p> - -<p>The primary API for rendering into the DOM looks like this:</p> -<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="nx">reactElement</span><span class="p">,</span> <span class="nx">domContainerNode</span><span class="p">)</span> -</code></pre></div> -<p>To update the properties of an existing component, you call render again with a new element.</p> - -<p>If you are rendering React components within a single-page app, you may need to plug into the app&#39;s view lifecycle to ensure your app will invoke unmountComponentAtNode at the appropriate time. React will not automatically clean up a tree. You need to manually call:</p> -<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">unmountComponentAtNode</span><span class="p">(</span><span class="nx">domContainerNode</span><span class="p">)</span> -</code></pre></div> -<p>This is important and often forgotten. Forgetting to call <code>unmountComponentAtNode</code> will cause your app to leak memory. There is no way for us to automatically detect when it is appropriate to do this work. Every system is different.</p> - -<p>It is not unique to the DOM. If you want to insert a React Native view in the middle of an existing iOS app you will hit similar issues.</p> -<h2><a class="anchor" name="helpers"></a>Helpers <a class="hash-link" href="#helpers">#</a></h2> -<p>If you have multiple React roots, or a single root that gets deleted over time, we recommend that you always create your own wrapper API. These will all look slightly different depending on what your outer system looks like. For example, at Facebook we have a system that automatically ties into our page transition router to automatically call <code>unmountComponentAtNode</code>.</p> - -<p>Rather than calling <code>ReactDOM.render()</code> directly everywhere, consider writing/using a library that will manage mounting and unmounting within your application.</p> - -<p>In your environment you may want to always configure internationalization, routers, user data etc. If you have many different React roots it can be a pain to set up configuration nodes all over the place. By creating your own wrapper you can unify that configuration into one place.</p> -<h2><a class="anchor" name="object-oriented-updates"></a>Object Oriented Updates <a class="hash-link" href="#object-oriented-updates">#</a></h2> -<p>If you call <code>ReactDOM.render</code> a second time to update properties, all your props are completely replaced.</p> -<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">App</span> <span class="nx">locale</span><span class="o">=</span><span class="s2">&quot;en-US&quot;</span> <span class="nx">userID</span><span class="o">=</span><span class="p">{</span><span class="mi">1</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> -<span class="c1">// props.userID == 1</span> -<span class="c1">// props.locale == &quot;en-US&quot;</span> -<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o">&lt;</span><span class="nx">App</span> <span class="nx">userID</span><span class="o">=</span><span class="p">{</span><span class="mi">2</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span> -<span class="c1">// props.userID == 2</span> -<span class="c1">// props.locale == undefined ??!?</span> -</code></pre></div> -<p>In object-oriented programming, all state lives on each object instance and you apply changes incrementally by mutating that state, one piece at a time. If you are using React within an app that expects an object oriented API (for instance, if you are building a custom web component using React), it might be surprising/confusing to a user that setting a single property would wipe out all the other properties on your component.</p> - -<p>We used to have a helper function called <code>setProps</code> which allowed you to update only a few properties at a time. Unfortunately this API lived on a component instance, required React to keep this state internally and wasn&#39;t very natural anyway. Therefore, we&#39;re deprecating it and suggest that you build it into your own wrapper instead.</p> - -<p>Here&#39;s some boilerplate to get you started. It is a 0.14 migration path for codebases using <code>setProps</code> and <code>replaceProps</code>.</p> -<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="kr">class</span> <span class="nx">ReactComponentRenderer</span> <span class="p">{</span> - <span class="nx">constructor</span><span class="p">(</span><span class="nx">klass</span><span class="p">,</span> <span class="nx">container</span><span class="p">)</span> <span class="p">{</span> - <span class="k">this</span><span class="p">.</span><span class="nx">klass</span> <span class="o">=</span> <span class="nx">klass</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">container</span> <span class="o">=</span> <span class="nx">container</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">props</span> <span class="o">=</span> <span class="p">{};</span> - <span class="k">this</span><span class="p">.</span><span class="nx">component</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> - <span class="p">}</span> - - <span class="nx">replaceProps</span><span class="p">(</span><span class="nx">props</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span> - <span class="k">this</span><span class="p">.</span><span class="nx">props</span> <span class="o">=</span> <span class="p">{};</span> - <span class="k">this</span><span class="p">.</span><span class="nx">setProps</span><span class="p">(</span><span class="nx">props</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span> - <span class="p">}</span> - - <span class="nx">setProps</span><span class="p">(</span><span class="nx">partialProps</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span> - <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">klass</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> - <span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span> - <span class="s1">&#39;setProps(...): Can only update a mounted or &#39;</span> <span class="o">+</span> - <span class="s1">&#39;mounting component. This usually means you called setProps() on &#39;</span> <span class="o">+</span> - <span class="s1">&#39;an unmounted component. This is a no-op.&#39;</span> - <span class="p">);</span> - <span class="k">return</span><span class="p">;</span> - <span class="p">}</span> - <span class="nb">Object</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">,</span> <span class="nx">partialProps</span><span class="p">);</span> - <span class="kd">var</span> <span class="nx">element</span> <span class="o">=</span> <span class="nx">React</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">klass</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">props</span><span class="p">);</span> - <span class="k">this</span><span class="p">.</span><span class="nx">component</span> <span class="o">=</span> <span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">container</span><span class="p">,</span> <span class="nx">callback</span><span class="p">);</span> - <span class="p">}</span> - - <span class="nx">unmount</span><span class="p">()</span> <span class="p">{</span> - <span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">unmountComponentAtNode</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">container</span><span class="p">);</span> - <span class="k">this</span><span class="p">.</span><span class="nx">klass</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> - <span class="p">}</span> -<span class="p">}</span> -</code></pre></div> -<p>Object-oriented APIs don&#39;t look like that though. They use setters and methods. I think we can do better. If you know more about the component API that you&#39;re rendering, you can create a more natural object-oriented API around your React component.</p> -<div class="highlight"><pre><code class="language-js" data-lang="js"><span class="kr">class</span> <span class="nx">ReactVideoPlayer</span> <span class="p">{</span> - <span class="nx">constructor</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="nx">container</span><span class="p">)</span> <span class="p">{</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_container</span> <span class="o">=</span> <span class="nx">container</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_url</span> <span class="o">=</span> <span class="nx">url</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_isPlaying</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_render</span><span class="p">();</span> - <span class="p">}</span> - - <span class="nx">_render</span><span class="p">()</span> <span class="p">{</span> - <span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span> - <span class="o">&lt;</span><span class="nx">VideoPlayer</span> <span class="nx">url</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">_url</span><span class="p">}</span> <span class="nx">playing</span><span class="o">=</span><span class="p">{</span><span class="k">this</span><span class="p">.</span><span class="nx">_isPlaying</span><span class="p">}</span> <span class="o">/&gt;</span><span class="p">,</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_container</span> - <span class="p">);</span> - <span class="p">}</span> - - <span class="nx">get</span> <span class="nx">url</span><span class="p">()</span> <span class="p">{</span> - <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_url</span><span class="p">;</span> - <span class="p">}</span> - - <span class="nx">set</span> <span class="nx">url</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_url</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_render</span><span class="p">();</span> - <span class="p">}</span> - - <span class="nx">play</span><span class="p">()</span> <span class="p">{</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_isPlaying</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_render</span><span class="p">();</span> - <span class="p">}</span> - - <span class="nx">pause</span><span class="p">()</span> <span class="p">{</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_isPlaying</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span> - <span class="k">this</span><span class="p">.</span><span class="nx">_render</span><span class="p">();</span> - <span class="p">}</span> - - <span class="nx">destroy</span><span class="p">()</span> <span class="p">{</span> - <span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">unmountComponentAtNode</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_container</span><span class="p">);</span> - <span class="p">}</span> -<span class="p">}</span> -</code></pre></div> -<p>This example shows how to provide an imperative API on top of a declarative one. Similarly, the reverse can be done, and a declarative wrapper can be used when exposing a Web Component as a React component.</p> - - 2015-10-01T00:00:00-07:00 - https://facebook.github.io/react/blog/2015/10/01/react-render-and-top-level-api.html - https://facebook.github.io/react/blog/2015/10/01/react-render-and-top-level-api.html - -