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:
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:
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 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 @@
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:
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:
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.
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.
+ 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.
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:
+
+
+
Get the module dependencies for the application installed by running npm install.
+
Create a directory __tests__/ with a test file, in this case TodoStore-test.js
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.
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 mockproperty 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:
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.
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.
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.
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.
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:
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:
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.
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.
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.
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.
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!
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.
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.
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.
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.
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!
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?
Andrey Popp's react-quickstart, which gives you a quick template for server-side rendering and routing, among other features.
-
-
-
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!
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.
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.
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.
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.
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?
Andrey Popp's react-quickstart, which gives you a quick template for server-side rendering and routing, among other features.
+
+
+
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!
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.
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.
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.
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.
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:
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.
-varinstance=<MyComponent/>;
-React.renderComponent(instance);
-// ...
-instance.setProps(...);
-
-// The change here is very simple. The return value of renderComponent will be
-// the mounted instance.
-varinstance=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.
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.
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:
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.
+varinstance=<MyComponent/>;
+React.renderComponent(instance);
+// ...
+instance.setProps(...);
+
+// The change here is very simple. The return value of renderComponent will be
+// the mounted instance.
+varinstance=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.
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.
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:
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:
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.
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
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:
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:
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.
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
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!
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.
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.
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!
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!
-
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.
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!
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.
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.
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!
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!
+
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.
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.
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.
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):
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.
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.
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.
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.
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.
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):
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.
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.
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.
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.
Dependencies will be registered for any data accesses performed by getMeteorState so that the component can be automatically re-rendered whenever the data changes.
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.
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.
Dependencies will be registered for any data accesses performed by getMeteorState so that the component can be automatically re-rendered whenever the data changes.
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.
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).
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.
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.
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).
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.
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.
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.
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
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.
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.
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.
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.
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
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.
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.
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.
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
+
+ Next Page »
+
+
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 @@
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.
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:
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.
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.
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.
-
classReactComponentRenderer{
- 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);
- varelement=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.
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.
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.
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:
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.
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.
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.
+
classReactComponentRenderer{
+ 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);
+ varelement=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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.”
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.
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.”
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.
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).
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:
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.
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.
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).
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:
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 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?
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.
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.
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:
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.
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.
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?
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
React.addons.update uses assign instead of copyProperties which does hasOwnProperty checks. Properties on prototypes will no longer be updated correctly.
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.
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.
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.
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.
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.
React.addons.update uses assign instead of copyProperties which does hasOwnProperty checks. Properties on prototypes will no longer be updated correctly.
- 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.
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:
-
-
-
Get the module dependencies for the application installed by running npm install.
-
Create a directory __tests__/ with a test file, in this case TodoStore-test.js
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.
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 mockproperty 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:
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.
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.
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.
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.
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:
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:
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.
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:
계층구조의 컴포넌트들을 가지고 있으니, 이젠 애플리케이션을 구현할 시간입니다. 가장 쉬운 방법은 상호작용을 하지 않는 채로 자료 모델을 이용해 UI를 그리는 것입니다. 정적 버전을 만드는 데에는 적은 생각과 많은 노동이 필요하고, 상호작용을 추가하는 데에는 많은 생각과 적은 노동이 필요하기 때문에 둘을 분리하는 것이 가장 좋습니다. 왜 그런지 봅시다.
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.
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.
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.
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.
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.
要让你的 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 项目的数组长度作为替代。
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 "if <code>componentWillReceiveProps</code> is called, then the props must have changed", 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: "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 <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">'componentWillReceiveProps'</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"><</span><span class="nx">div</span><span class="o">></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">!<</span><span class="err">/div>;</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">'container'</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">'drinks'</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"><</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">/></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"><</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">/></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"><</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">/></span><span class="p">,</span> <span class="nx">container</span><span class="p">);</span>
+</code></pre></div>
+<p>In this case, the answer is "2". React calls <code>componentWillReceiveProps</code> twice (once for each of the two updates). Both times, the value of "drinks" 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">'drinks'</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"><</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">/></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">'food'</span>
+<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o"><</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">/></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">'noise'</span>
+<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o"><</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">/></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'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'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.</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'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"><</span><span class="nx">App</span> <span class="nx">locale</span><span class="o">=</span><span class="s2">"en-US"</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">/></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 == "en-US"</span>
-<span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="o"><</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">/></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't very natural anyway. Therefore, we're deprecating it and suggest that you build it into your own wrapper instead.</p>
-
-<p>Here'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">'setProps(...): Can only update a mounted or '</span> <span class="o">+</span>
- <span class="s1">'mounting component. This usually means you called setProps() on '</span> <span class="o">+</span>
- <span class="s1">'an unmounted component. This is a no-op.'</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'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.</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"><</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">/></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
-
-