diff --git a/404.html b/404.html index d84af23704..2ef40ca463 100644 --- a/404.html +++ b/404.html @@ -63,7 +63,7 @@
@@ -122,7 +122,7 @@react-tools package, which has been updated. We've copied over the changelog from the RC with some small clarifying changes.
+
@@ -64,7 +64,7 @@
@@ -240,7 +240,7 @@ Minified build for production:
The conference is over, but the conversation has just begun.
-Mihai Parparita detailed his efforts to hack his way to a React.js Conf ticket; James Long blogged about his first encounter with React Native; Eric Florenzano talked about how he perceives the impact of Relay, GraphQL, and React Native on software development; Margaret Staples blogged about her experience of being on-campus at Facebook HQ; Jeff Barczewski tied his experience of attending the conference up with a bow in this blog post filled with photos, videos, and links; Kevin Old left us with his takeaways; Paul Wittmann found React Native freshly on his radar; and finally, undeterred by not being able to attend the conference in person, Justin Ball summarized it from afar.
+Mihai Parparita detailed his efforts to hack his way to a React.js Conf ticket; James Long blogged about his first encounter with React Native; Eric Florenzano talked about how he perceives the impact of Relay, GraphQL, and React Native on software development; Margaret Staples blogged about her experience of being on-campus at Facebook HQ; Jeff Barczewski tied his experience of attending the conference up with a bow in this blog post filled with photos, videos, and links; Kevin Old left us with his takeaways; Paul Wittmann found React Native freshly on his radar; and finally, undeterred by not being able to attend the conference in person, Justin Ball summarized it from afar.
And, in case you missed a session, you can borrow Michael Chan’s drawings, Mihai Parparita’s summary, or Shaohua Zhou’s day 1 / day 2 notes.
@@ -435,7 +435,7 @@
In its earliest days, React benefitted tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.
+In its earliest days, React benefited tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.
React's approach to building user interfaces with functional programming principles has changed the way we do things in just a few short years. It goes without saying, but React would be nothing without the amazing open source community that's built up around it!
@@ -389,7 +389,7 @@ I think we should just treat arrays of elements as a frag. This is useful for co
In its earliest days, React benefitted tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.
+In its earliest days, React benefited tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.
React's approach to building user interfaces with functional programming principles has changed the way we do things in just a few short years. It goes without saying, but React would be nothing without the amazing open source community that's built up around it!
@@ -1398,7 +1398,7 @@ The console output is tuned to be minimal to help you focus on the problems:The conference is over, but the conversation has just begun.
-Mihai Parparita detailed his efforts to hack his way to a React.js Conf ticket; James Long blogged about his first encounter with React Native; Eric Florenzano talked about how he perceives the impact of Relay, GraphQL, and React Native on software development; Margaret Staples blogged about her experience of being on-campus at Facebook HQ; Jeff Barczewski tied his experience of attending the conference up with a bow in this blog post filled with photos, videos, and links; Kevin Old left us with his takeaways; Paul Wittmann found React Native freshly on his radar; and finally, undeterred by not being able to attend the conference in person, Justin Ball summarized it from afar.
+Mihai Parparita detailed his efforts to hack his way to a React.js Conf ticket; James Long blogged about his first encounter with React Native; Eric Florenzano talked about how he perceives the impact of Relay, GraphQL, and React Native on software development; Margaret Staples blogged about her experience of being on-campus at Facebook HQ; Jeff Barczewski tied his experience of attending the conference up with a bow in this blog post filled with photos, videos, and links; Kevin Old left us with his takeaways; Paul Wittmann found React Native freshly on his radar; and finally, undeterred by not being able to attend the conference in person, Justin Ball summarized it from afar.
And, in case you missed a session, you can borrow Michael Chan’s drawings, Mihai Parparita’s summary, or Shaohua Zhou’s day 1 / day 2 notes.
@@ -922,7 +922,7 @@ Facebook will make determinations on scholarship recipients in its sole discretiJanuary 20-21 in Dornbirn, Austria
+March 13-14 in Santa Clara, CA
+ +May 18th & 19th in Paris, France
@@ -232,7 +236,7 @@Facebook engineers Bill Fisher and Jing Chen talk about Flux and React at Forward JS 2014, and how using an application architecture with a unidirectional data flow cleans up a lot of their code.
-Walk-through by Andres Suarez on how SoundCloud is using React and Flux for server-side rendering.
- -@@ -306,7 +302,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/contributing/codebase-overview.html b/contributing/codebase-overview.html index 6484213137..a4d15ada74 100644 --- a/contributing/codebase-overview.html +++ b/contributing/codebase-overview.html @@ -63,7 +63,7 @@ @@ -248,7 +248,7 @@ You can runnpm run flowlocally to check your code with Flow.The
-Mixinin this code has no relation to Reactmixinsfeature. It is just a way of grouping a few methods under an object. Those methods may later get attached to some other class. We use this pattern in a few places although we try to avoid it in the new code.Equivalent code in ES6 would like this:
+Equivalent code in ES6 would look like this:
@@ -699,7 +704,7 @@ You can runclass ReactDOMComponent { constructor(element) { this._currentElement = element; @@ -341,7 +341,7 @@ You can runnpm run flowlocally to check your code with Flow.The only other officially supported renderer is
-react-art. To avoid accidentally breaking it as we make changes to React, we checked it in assrc/renderers/artand run its test suite. Nevertheless, its GitHub repository still acts as the source of truth.While it is technically possible to create custom React renderer, this is currently not officially supported. There is no stable public contract for custom renderers yet which is another reason why we keep them all in a single place.
+While it is technically possible to create custom React renderers, this is currently not officially supported. There is no stable public contract for custom renderers yet which is another reason why we keep them all in a single place.
Note:
@@ -367,7 +367,7 @@ You can runnpm run flowlocally to check your code with Flow.Composite Components #
User-defined ("composite") components should behave the same way with all renderers. This is why the stack reconciler provides a shared implementation in
-ReactCompositeComponent. It is always the same regardless of the renderer.Composite components also implement mounting, updating, and unmounting. However, unlike host components,
+ReactCompositeComponentneeds to behave differently depending on user's code. This is why it calls methods, such asrender()andcomponentDidMount(), on the user-supplied class.Composite components also implement mounting, updating, and unmounting. However, unlike host components,
ReactCompositeComponentneeds to behave differently depending on the user's code. This is why it calls methods, such asrender()andcomponentDidMount(), on the user-supplied class.During an update,
ReactCompositeComponentchecks whether therender()output has a differenttypeorkeythan the last time. If neithertypenorkeyhas changed, it delegates the update to the existing child internal instance. Otherwise, it unmounts the old child instance and mounts a new one. This is described in the reconciliation algorithm.Recursion #
@@ -545,6 +545,11 @@ You can runnpm run flowlocally to check your code with Flow. ++ Higher-Order Components + + +npm run flowlocally to check your code with Flow.![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/contributing/design-principles.html b/contributing/design-principles.html index 4b834f8089..abe6ab0dff 100644 --- a/contributing/design-principles.html +++ b/contributing/design-principles.html @@ -63,7 +63,7 @@ @@ -342,6 +342,11 @@ ++ Higher-Order Components + + + @@ -496,7 +501,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/contributing/how-to-contribute.html b/contributing/how-to-contribute.html index 6c1620c591..6dd59d063a 100644 --- a/contributing/how-to-contribute.html +++ b/contributing/how-to-contribute.html @@ -63,7 +63,7 @@ @@ -103,7 +103,7 @@There is also an active community of React users on the Discord chat platform in case you need help with React.
Proposing a Change #
-If you intend to change to the public API, or make any non-trivial changes to the implementation, we recommend filing an issue. This lets us reach an agreement on your proposal before you put significant effort into it.
+If you intend to change the public API, or make any non-trivial changes to the implementation, we recommend filing an issue. This lets us reach an agreement on your proposal before you put significant effort into it.
If you're only fixing a bug, it's fine to submit a pull request right away but we still recommend to file an issue detailing what you're fixing. This is helpful in case we don't accept that specific fix but want to keep track of the issue.
Your First Pull Request #
@@ -331,6 +331,11 @@ You can check the status of your code styling by simply runningnpm run li +- ++ Higher-Order Components + + + @@ -485,7 +490,7 @@ You can check the status of your code styling by simply runningnpm run li- +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/contributing/implementation-notes.html b/contributing/implementation-notes.html index 94353989b0..a9e53f528d 100644 --- a/contributing/implementation-notes.html +++ b/contributing/implementation-notes.html @@ -63,7 +63,7 @@ @@ -995,6 +995,11 @@ ++ Higher-Order Components + + + @@ -1149,7 +1154,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/addons.html b/docs/addons.html index 792ebf59a7..1d0128eeed 100644 --- a/docs/addons.html +++ b/docs/addons.html @@ -63,7 +63,7 @@ @@ -247,6 +247,11 @@ ++ Higher-Order Components + + + @@ -401,7 +406,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/animation.html b/docs/animation.html index 30a3c048c6..9fc92464f1 100644 --- a/docs/animation.html +++ b/docs/animation.html @@ -63,7 +63,7 @@ @@ -78,7 +78,7 @@ -The
+ReactTransitionGroupadd-on component is a low-level API for animation, andReactCSSTransitionGroupis an add-on component for easily implementing basic CSS animations and transitions.The
ReactTransitionGroupadd-on component is a low-level API for animation, andReactCSSTransitionGroupis an add-on component for easily implementing basic CSS animations and transitions.High-level API: ReactCSSTransitionGroup #
@@ -473,6 +473,11 @@ +
ReactCSSTransitionGroupis a high-level API based onReactTransitionGroupand is an easy way to perform CSS transitions and animations when a React component enters or leaves the DOM. It's inspired by the excellent ng-animate library.+ Higher-Order Components + + + @@ -627,7 +632,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/components-and-props.html b/docs/components-and-props.html index 62310abddc..3848cb6f07 100644 --- a/docs/components-and-props.html +++ b/docs/components-and-props.html @@ -63,7 +63,7 @@ @@ -424,6 +424,11 @@ ++ Higher-Order Components + + + @@ -578,7 +583,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/composition-vs-inheritance.html b/docs/composition-vs-inheritance.html index 319553e1fc..d4c53a9de0 100644 --- a/docs/composition-vs-inheritance.html +++ b/docs/composition-vs-inheritance.html @@ -63,7 +63,7 @@ @@ -360,6 +360,11 @@ ++ Higher-Order Components + + + @@ -514,7 +519,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/conditional-rendering.html b/docs/conditional-rendering.html index f220fc063c..980d327769 100644 --- a/docs/conditional-rendering.html +++ b/docs/conditional-rendering.html @@ -63,7 +63,7 @@ @@ -106,7 +106,7 @@ document.getElementById('root') );This example renders a different greeting depending on the value of
isLoggedInprop.Element Variables #
@@ -172,7 +172,7 @@ document.getElementById('root') );While declaring a variable and using an
ifstatement is a fine way to conditionally render a component, sometimes you might want to use a shorter syntax. There are a few ways to inline conditions in JSX, explained below.Inline If with Logical && Operator #
@@ -276,7 +276,9 @@ document.getElementById('root') ); - + + +Returning
nullfrom a component'srendermethod does not affect the firing of the component's lifecycle methods. For instance,componentWillUpdateandcomponentDidUpdatewill still be called.@@ -418,6 +420,11 @@ +@@ -572,7 +579,7 @@+ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/conferences-it-IT.html b/docs/conferences-it-IT.html index cf53488bb6..8546358919 100644 --- a/docs/conferences-it-IT.html +++ b/docs/conferences-it-IT.html @@ -63,7 +63,7 @@ @@ -180,7 +180,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/conferences-ko-KR.html b/docs/conferences-ko-KR.html index 2251729ab2..c2ef7ec9b2 100644 --- a/docs/conferences-ko-KR.html +++ b/docs/conferences-ko-KR.html @@ -63,7 +63,7 @@ @@ -180,7 +180,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/conferences-zh-CN.html b/docs/conferences-zh-CN.html index 0c8f80924e..8b06552742 100644 --- a/docs/conferences-zh-CN.html +++ b/docs/conferences-zh-CN.html @@ -63,7 +63,7 @@ @@ -188,7 +188,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/context.html b/docs/context.html index 13f6928a73..a23190c61f 100644 --- a/docs/context.html +++ b/docs/context.html @@ -63,7 +63,7 @@ @@ -385,6 +385,11 @@ You can do this directly in React with the powerful "context" API. ++ Higher-Order Components + + + @@ -539,7 +544,7 @@ You can do this directly in React with the powerful "context" API.![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/create-fragment.html b/docs/create-fragment.html index 58e84932fc..03cbd36abd 100644 --- a/docs/create-fragment.html +++ b/docs/create-fragment.html @@ -63,7 +63,7 @@ @@ -263,6 +263,11 @@ ++ Higher-Order Components + + + @@ -417,7 +422,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/dom-elements.html b/docs/dom-elements.html index 6d2c37e361..4990d5f8dd 100644 --- a/docs/dom-elements.html +++ b/docs/dom-elements.html @@ -63,7 +63,7 @@ @@ -193,8 +193,8 @@ underlineThickness unicode unicodeBidi unicodeRange unitsPerEm vAlphabetic vHanging vIdeographic vMathematical values vectorEffect version vertAdvY vertOriginX vertOriginY viewBox viewTarget visibility widths wordSpacing writingMode x x1 x2 xChannelSelector xHeight xlinkActuate xlinkArcrole -xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlBase xmlLang xmlSpace -y y1 y2 yChannelSelector z zoomAndPan +xlinkHref xlinkRole xlinkShow xlinkTitle xlinkType xmlns xmlnsXlink xmlBase +xmlLang xmlSpace y y1 y2 yChannelSelector z zoomAndPan@@ -332,6 +332,11 @@ y y1 y2 yChannelSelector z zoomAndPan +@@ -486,7 +491,7 @@ y y1 y2 yChannelSelector z zoomAndPan+ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/error-decoder.html b/docs/error-decoder.html index 61960d8aa0..09e3de6ccf 100644 --- a/docs/error-decoder.html +++ b/docs/error-decoder.html @@ -63,7 +63,7 @@ @@ -224,6 +224,11 @@ ++ Higher-Order Components + + + @@ -378,7 +383,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/events.html b/docs/events.html index a69cbd4eba..b244518581 100644 --- a/docs/events.html +++ b/docs/events.html @@ -63,7 +63,7 @@ @@ -437,6 +437,11 @@ onTimeUpdate onVolumeChange onWaiting ++ Higher-Order Components + + + @@ -591,7 +596,7 @@ onTimeUpdate onVolumeChange onWaiting![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/forms-zh-CN.html b/docs/forms-zh-CN.html new file mode 100644 index 0000000000..61cf51283c --- /dev/null +++ b/docs/forms-zh-CN.html @@ -0,0 +1,10 @@ + + + +Redirecting… + + +Redirecting…
+Click here if you are not redirected. + + diff --git a/docs/forms.html b/docs/forms.html index a575036ad9..51d11c6711 100644 --- a/docs/forms.html +++ b/docs/forms.html @@ -63,7 +63,7 @@ @@ -366,6 +366,11 @@ ++ Higher-Order Components + + + @@ -520,7 +525,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/handling-events.html b/docs/handling-events.html index e8f0a76301..f4f862229c 100644 --- a/docs/handling-events.html +++ b/docs/handling-events.html @@ -63,7 +63,7 @@ @@ -331,6 +331,11 @@ ++ Higher-Order Components + + + @@ -485,7 +490,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/hello-world.html b/docs/hello-world.html index ddfb3bb41c..1caa3dcbd1 100644 --- a/docs/hello-world.html +++ b/docs/hello-world.html @@ -63,7 +63,7 @@ @@ -234,6 +234,11 @@ ++ Higher-Order Components + + + @@ -388,7 +393,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/higher-order-components.html b/docs/higher-order-components.html new file mode 100644 index 0000000000..47183f79c2 --- /dev/null +++ b/docs/higher-order-components.html @@ -0,0 +1,750 @@ + + + + + + + + +Higher-Order Components - React + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ++ + + + ++ + + + + diff --git a/docs/installation.html b/docs/installation.html index 76179fa54c..db328fd5b5 100644 --- a/docs/installation.html +++ b/docs/installation.html @@ -63,7 +63,7 @@ @@ -100,17 +100,19 @@ npm start+ + + + + ++ Edit on GitHub ++ + + ++ Higher-Order Components +
+ + +A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React's compositional nature.
+ +Concretely, a higher-order component is a function that takes a component and returns a new component.
++const EnhancedComponent = higherOrderComponent(WrappedComponent); +Whereas a component transforms props into UI, a higher-order component transforms a component into another component.
+ +HOCs are common in third-party React libraries, such as Redux's
+ +connectand Relay'screateContainer.In this document, we'll discuss why higher-order components are useful, and how to write your own.
+Use HOCs For Cross-Cutting Concerns #
+++ +Note
+ +We previously recommended mixins as a way to handle cross-cutting concerns. We've since realized that mixins create more trouble than they are worth. Read more about why we've moved away from mixins and how you can transition your existing components.
+Components are the primary unit of code reuse in React. However, you'll find that some patterns aren't a straightforward fit for traditional components.
+ +For example, say you have a
+CommentListcomponent that subscribes to an external data source to render a list of comments:+class CommentList extends React.Component { + constructor() { + super(); + this.handleChange = this.handleChange.bind(this); + this.state = { + // "DataSource" is some global data source + comments: DataSource.getComments() + }; + } + + componentDidMount() { + // Subscribe to changes + DataSource.addChangeListener(this.handleChange); + } + + componentWillUnmount() { + // Clean up listener + DataSource.removeChangeListener(this.handleChange); + } + + handleChange() { + // Update component state whenever the data source changes + this.setState({ + comments: DataSource.getComments() + }); + } + + render() { + return ( + <div> + {this.state.comments.map((comment) => ( + <Comment comment={comment} key={comment.id} /> + ))} + </div> + ); + }} +Later, you write a component for subscribing to a single blog post, which follows a similar pattern:
++class BlogPost extends React.Component { + constructor() { + super(); + this.handleChange = this.handleChange.bind(this); + this.state = { + blogPost: DataSource.getBlogPost(props.id) + }; + } + + componentDidMount() { + DataSource.addChangeListener(this.handleChange); + } + + componentWillUnmount() { + DataSource.removeChangeListener(this.handleChange); + } + + handleChange() { + this.setState({ + blogPost: DataSource.getBlogPost(this.props.id) + }); + } + + render() { + return <BlogPost blogPost={this.state.blogPost} />; + }} ++ +
CommentListandBlogPostaren't identical — they call different methods onDataSource, and they render different output. But much of their implementation is the same:+
+ +- On mount, add a change listener to
+DataSource.- Inside the listener, call
+setStatewhenever the data source changes.- On unmount, remove the change listener.
+You can imagine that in a large app, this same pattern of subscribing to
+ +DataSourceand callingsetStatewill occur over and over again. We want an abstraction that allows us to define this logic in a single place and share them across many components. This is where higher-order components excel.We can write a function that creates components, like
+CommentListandBlogPost, that subscribe toDataSource. The function will accept as one of its arguments a child component that receives the subscribed data as a prop. Let's call the functionwithSubscription:+const CommentListWithSubscription = withSubscription( + CommentList, + (DataSource) => DataSource.getComments() +); + +const BlogPostWithSubscription = withSubscription( + BlogPost, + (DataSource, props) => DataSource.getBlogPost(props.id) +}); +The first parameter is the wrapped component. The second parameter retrieves the data we're interested in, given a
+ +DataSourceand the current props.When
+CommentListWithSubscriptionandBlogPostWithSubscriptionare rendered,CommentListandBlogPostwill be passed adataprop with the most current data retrieved fromDataSource:+// This function takes a component... +function withSubscription(WrappedComponent, selectData) { + // ...and returns another component... + return class extends React.Component { + constructor(props) { + super(props); + this.handleChange = this.handleChange.bind(this); + this.state = { + data: selectData(DataSource, props) + }; + } + + componentDidMount() { + // ... that takes care of the subscription... + DataSource.addChangeListener(this.handleChange); + } + + componentWillUnmount() { + DataSource.removeChangeListener(this.handleChange); + } + + handleChange() { + this.setState({ + comments: selectData(DataSource, this.props) + }); + } + + render() { + // ... and renders the wrapped component with the fresh data! + // Notice that we pass through any additional props + return <WrappedComponent data={this.state.data} {...this.props} />; + } + }); +} +Note that an HOC doesn't modify the input component, nor does it use inheritance to copy its behavior. Rather, an HOC composes the original component by wrapping it in a container component. An HOC is a pure function with zero side-effects.
+ +And that's it! The wrapped component receives all the props of the container, along with a new prop,
+ +data, which it uses to render its output. The HOC isn't concerned with how or why the data is used, and the wrapped component isn't concerned with where the data came from.Because
+ +withSubscriptionis a normal function, you can add as many or as few arguments as you like. For example, you may want to make the name of thedataprop configurable, to further isolate the HOC from the wrapped component. Or you could accept an argument that configuresshouldComponentUpdate, or one that configures the data source. These are all possible because the HOC has full control over how the component is defined.Like components, the contract between
+withSubscriptionand the wrapped component is entirely props-based. This makes it easy to swap one HOC for a different one, as long as they provide the same props to the wrapped component. This may be useful if you change data-fetching libraries, for example.Don't Mutate the Original Component. Use Composition. #
+Resist the temptation to modify a component's prototype (or otherwise mutate it) inside an HOC.
++function logProps(InputComponent) { + InputComponent.prototype.componentWillReceiveProps(nextProps) { + console.log('Current props: ', this.props); + console.log('Next props: ', nextProps); + } + // The fact that we're returning the original input is a hint that it has + // been mutated. + return InputComponent; +} + +// EnhancedComponent will log whenever props are received +const EnhancedComponent = logProps(InputComponent); +There are a few problems with this. One is that the input component cannot be reused separately from the enhanced component. More crucially, if you apply another HOC to
+ +EnhancedComponentthat also mutatesshouldComponentUpdate, the first HOC's functionality will be overridden! This HOC also won't work with function components, which do not have lifecycle methods.Mutating HOCs are a leaky abstraction—the consumer must know how they are implemented in order to avoid conflicts with other HOCs.
+ +Instead of mutation, HOCs should use composition, by wrapping the input component in a container component:
++function logProps(WrappedComponent) { + return class extends React.Component { + componentWillReceiveProps(nextProps) { + console.log('Current props: ', this.props); + console.log('Next props: ', nextProps); + } + render() { + // Wraps the input component in a container, without mutating it. Good! + return <WrappedComponent {...this.props} />; + } + } +} +This HOC has the same functionality as the mutating version while avoiding the potential for clashes. It works equally well with class and functional components. And because it's a pure function, it's composable with other HOCs, or even with itself.
+ +You may have noticed similarities between HOCs and a pattern called container components. Container components are part of a strategy of separating responsibility between high-level and low-level concerns. Containers manage things like subscriptions and state, and pass props to components that handle things like rendering UI. HOCs use containers as part of their implementation. You can think of HOCs as parameterized container component definitions.
+Convention: Pass Unrelated Props Through to the Wrapped Component #
+HOCs add features to a component. They shouldn't drastically alter its contract. It's expected that the component returned from an HOC has a similar interface to the wrapped component.
+ +HOCs should pass through props that are unrelated to its specific concern. Most HOCs contain a render method that looks something like this:
++render() { + // Filter out extra props that are specific to this HOC and shouldn't be + // passed through + const { extraProp, ...passThroughProps } = this.props; + + // Inject props into the wrapped component. These are usually state values or + // instance methods. + const injectedProp = someStateOrInstanceMethod; + + // Pass props to wrapped component + return ( + <WrappedComponent + injectedProp={injectedProp} + {...passThroughProps} + /> + ); +} +This convention helps ensure that HOCs are as flexible and reusable as possible.
+Convention: Maximizing Composability #
+Not all HOCs look the same. Sometimes they accept only a single argument, the wrapped component:
++const NavbarWithRouter = withRouter(Navbar); +Usually, HOCs accept additional arguments. In this example from Relay, a config object is used to specify a component's data dependencies:
++const CommentWithRelay = Relay.createContainer(Comment, config); +The most common signature for HOCs looks like this:
++// React Redux's `connect` +const ConnectedComment = connect(commentSelector, commentActions)(Comment); +What?! If you break it apart, it's easier to see what's going on.
++// connect is a function that returns another function +const enhance = connect(commentListSelector, commentListActions); +// The returned function is an HOC, which returns a component that is connected +// to the Redux store +const ConnectedComment = enhance(CommentList); +In other words,
+ +connectis a higher-order function that returns a higher-order component!This form may seem confusing or unnecessary, but it has a useful property. Single-argument HOCs like the one returned by the
+connectfunction have the signatureComponent => Component. Functions whose output type is the same as its input type are really easy to compose together.+// Instead of doing this... +const EnhancedComponent = connect(commentSelector)(withRouter(WrappedComponent)) + +// ... you can use a function composition utility +// compose(f, g, h) is the same as (...args) => f(g(h(...args))) +const enhance = compose( + // These are both single-argument HOCs + connect(commentSelector), + withRouter +) +const EnhancedComponent = enhance(WrappedComponent) +(This same property also allows
+ +connectand other enhancer-style HOCs to be used as decorators, an experimental JavaScript proposal.)The
+composeutility function is provided by many third-party libraries including lodash (aslodash.flowRight), Redux, and Rambda.Convention: Wrap the Display Name for Easy Debugging #
+The container components created by HOCs show up in the React Developer Tools like any other component. To ease debugging, choose a display name that communicates that it's the result of an HOC.
+ +The most common technique is to wrap the display name of the wrapped component. So if your higher-order component is named
+withSubscription, and the wrapped component's display name isCommentList, use the display nameWithSubscription(CommentList):function withSubscription(WrappedComponent) { + class WithSubscription extends React.Component {/* ... */} + WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`; + return WithSubscription; +} + +function getDisplayName(WrappedComponent) { + return WrappedComponent.displayName || WrappedComponent.name || 'Component'; +} +Caveats #
+Higher-order components come with a few caveats that aren't immediately obvious if you're new to React.
+Don't Use HOCs Inside the render Method #
+React's diffing algorithm (called reconciliation) uses component identity to determine whether it should update the existing subtree or throw it away and mount a new one. If the component returned from
+ +renderis identical (===) to the component from the previous render, React recursively updates the subtree by diffing it with the new one. If they're not equal, the previous subtree is unmounted completely.Normally, you shouldn't need to think about this. But it matters for HOCs because it means you can't apply an HOC to a component within the render method of a component:
++render() { + // A new version of EnhancedComponent is created on every render + // EnhancedComponent1 !== EnhancedComponent2 + const EnhancedComponent = enhance(MyComponent); + // That causes the entire subtree to unmount/remount each time! + return <EnhancedComponent />; +} +The problem here isn't just about performance — remounting a component causes the state of that component and all of its children to be lost.
+ +Instead, apply HOCs outside the component definition so that the resulting component is created only once. Then, its identity will be consistent across renders. This is usually what you want, anyway.
+ +In those rare cases where you need to apply an HOC dynamically, you can also do it inside a component's lifecycle methods or its constructor.
+Static Methods Must Be Copied Over #
+Sometimes it's useful to define a static method on a React component. For example, Relay containers expose a static method
+ +getFragmentto facilitate the composition of GraphQL fragments.When you apply an HOC to a component, though, the original component is wrapped with a container component. That means the new component does not have any of the static methods of the original component.
++// Define a static method +WrappedComponent.staticMethod = function() {/*...*/} +// Now apply an HOC +const EnhancedComponent = enhance(WrappedComponent); + +// The enhanced component has no static method +typeof EnhancedComponent.staticMethod === 'undefined' // true +To solve this, you could copy the methods onto the container before returning it:
++function enhance(WrappedComponent) { + class Enhance extends React.Component {/*...*/} + // Must know exactly which method(s) to copy :( + Enhance.staticMethod = WrappedComponent.staticMethod; + return Enhance; +} +However, this requires you to know exactly which methods need to be copied. You can use hoist-non-react-statics to automatically copy all non-React static methods:
++import hoistNonReactStatic from 'hoist-non-react-statics'; +function enhance(WrappedComponent) { + class Enhance extends React.Component {/*...*/} + hoistNonReactStatic(Enhance, WrappedComponent); + return Enhance; +} +Another possible solution is to export the static method separately from the component itself.
+// Instead of... +MyComponent.someFunction = someFunction; +export default MyComponent; + +// ...export the method separately... +export { someFunction }; + +// ...and in the consuming module, import both +import MyComponent, { someFunction } from './MyComponent.js'; +Refs Aren't Passed Through #
+While the convention for higher-order components is to pass through all props to the wrapped component, it's not possible to pass through refs. That's because
+ +refis not really a prop — likekey, it's handled specially by React. If you add a ref to an element whose component is the result of an HOC, the ref refers to an instance of the outermost container component, not the wrapped component.If you find yourself facing this problem, the ideal solution is to figure out how to avoid using
+ +refat all. Occasionally, users who are new to the React paradigm rely on refs in situations where a prop would work better.That said, there are times when refs are a necessary escape hatch — React wouldn't support them otherwise. Focusing an input field is an example where you may want imperative control of a component. In that case, one solution is to pass a ref callback as a normal prop, by giving it a different name:
++function Field({ inputRef, ...rest }) { + return <input ref={inputRef} {...rest} />; +} + +// Wrap Field in a higher-order component +const EnhancedField = enhance(Field); + +// Inside a class component's render method... +<EnhancedField + inputRef={(inputEl) => { + // This callback gets passed through as a regular prop + this.inputEl = inputEl + }} +/> + +// Now you can call imperative methods +this.inputEl.focus(); +This is not a perfect solution by any means. We prefer that refs remain a library concern, rather than require you to manually handle them. We are exploring ways to solve this problem so that using an HOC is unobservable.
+ + ++ + ++
- A package manager, such as Yarn or npm. It lets you take advantage of a vast ecosystem of third-party packages, and easily install or update them.
-- A bundler, such as webpack or Browserify. It lets you write modular code and bundle it together into small packages to optimize load time.
+- A bundler, such as webpack or Browserify. It lets you write modular code and bundle it together into small packages to optimize load time.
- A compiler such as Babel. It lets you write modern JavaScript code that still works in older browsers.
Installing React #
We recommend using Yarn or npm for managing front-end dependencies. If you're new to package managers, the Yarn documentation is a good place to get started.
To install React with Yarn, run:
-@@ -330,6 +330,11 @@ +yarn add react react-dom +yarn init +yarn add react react-domTo install React with npm, run:
-npm install --save react react-dom +npm init +npm install --save react react-domBoth Yarn and npm download packages from the npm registry.
Enabling ES6 and JSX #
@@ -118,7 +120,7 @@ npm startThe Babel setup instructions explain how to configure Babel in many different build environments. Make sure you install
babel-preset-reactandbabel-preset-es2015and enable them in your.babelrcconfiguration, and you're good to go.Hello World with ES6 and JSX #
-We recommend using a bundler like webpack or Browserify so you can write modular code and bundle it together into small packages to optimize load time.
+We recommend using a bundler like webpack or Browserify so you can write modular code and bundle it together into small packages to optimize load time.
The smallest React example looks like this:
@@ -445,7 +452,7 @@ npm startimport React from 'react'; @@ -291,6 +293,11 @@ npm start ++ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/introducing-jsx.html b/docs/introducing-jsx.html index 8085fa625f..5725155265 100644 --- a/docs/introducing-jsx.html +++ b/docs/introducing-jsx.html @@ -63,7 +63,7 @@+ Higher-Order Components + + + @@ -484,7 +489,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/jsx-in-depth.html b/docs/jsx-in-depth.html index d0c00f2385..4bcdf35a1b 100644 --- a/docs/jsx-in-depth.html +++ b/docs/jsx-in-depth.html @@ -63,7 +63,7 @@ @@ -198,7 +198,7 @@You can pass any JavaScript expression as a prop, by surrounding it with
{}. For example, in this JSX:-<MyComponent foo={1 + 2 + 3 + 4} />For
+MyComponent, The value ofprops.foowill be10because the expression1 + 2 + 3 + 4gets evaluated.For
MyComponent, the value ofprops.foowill be10because the expression1 + 2 + 3 + 4gets evaluated.
ifstatements andforloops are not expressions in JavaScript, so they can't be used in JSX directly. Instead, you can put these in the surrounding code. For example:@@ -654,7 +659,7 @@function NumberDescriber(props) { @@ -500,6 +500,11 @@ ++ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/lifting-state-up.html b/docs/lifting-state-up.html index 6aeafc7c5e..d5478c6185 100644 --- a/docs/lifting-state-up.html +++ b/docs/lifting-state-up.html @@ -63,7 +63,7 @@ @@ -419,6 +419,11 @@ ++ Higher-Order Components + + + @@ -573,7 +578,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/lists-and-keys.html b/docs/lists-and-keys.html index 79778d93c1..1a21c9cca8 100644 --- a/docs/lists-and-keys.html +++ b/docs/lists-and-keys.html @@ -63,7 +63,7 @@ @@ -103,7 +103,7 @@ document.getElementById('root') ); - +This code displays a bullet list of numbers between 1 and 5.
Basic List Component #
@@ -147,7 +147,7 @@ document.getElementById('root') ); - +Keys #
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:
- +const numbers = [1, 2, 3, 4, 5]; @@ -234,7 +234,7 @@ document.getElementById('root') );A good rule of thumb is that elements inside the
map()call need keys.Keys Must Only Be Unique Among Siblings #
@@ -273,7 +273,7 @@ document.getElementById('root') ); - +Keys serve as a hint to React but they don't get passed to your components. If you need the same value in your component, pass it explicitly as a prop with a different name:
- +const content = posts.map((post) => @@ -312,7 +312,7 @@ ); }Sometimes this results in clearer code, but this style can also be abused. Like in JavaScript, it is up to you to decide whether it is worth extracting a variable for readability. Keep in mind that if the
@@ -456,6 +456,11 @@ +map()body is too nested, it might be a good time to extract a component.+ Higher-Order Components + + + @@ -610,7 +615,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/optimizing-performance.html b/docs/optimizing-performance.html index 109a15a9a0..a287d5901c 100644 --- a/docs/optimizing-performance.html +++ b/docs/optimizing-performance.html @@ -63,7 +63,7 @@ @@ -138,11 +138,13 @@ } render() { - <button - color={this.props.color} - onClick={() => this.setState(state => ({count: state.count + 1}))}> - Count: {this.state.count} - </button> + return ( + <button + color={this.props.color} + onClick={() => this.setState(state => ({count: state.count + 1}))}> + Count: {this.state.count} + </button> + ); } } @@ -154,11 +156,13 @@ } render() { - <button - color={this.props.color} - onClick={() => this.setState(state => ({count: state.count + 1}))}> - Count: {this.state.count} - </button> + return ( + <button + color={this.props.color} + onClick={() => this.setState(state => ({count: state.count + 1}))}> + Count: {this.state.count} + </button> + ); } } @@ -394,6 +398,11 @@ ++ Higher-Order Components + + + @@ -548,7 +557,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/perf.html b/docs/perf.html index b87303fe7c..5c42bb8a5c 100644 --- a/docs/perf.html +++ b/docs/perf.html @@ -63,7 +63,7 @@ @@ -311,6 +311,11 @@ ++ Higher-Order Components + + + @@ -465,7 +470,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/pure-render-mixin.html b/docs/pure-render-mixin.html index 96f255d231..30af752768 100644 --- a/docs/pure-render-mixin.html +++ b/docs/pure-render-mixin.html @@ -63,7 +63,7 @@ @@ -81,7 +81,7 @@Note
-The
+PureRenderMixinmixin predatesReact.PureComponent. This reference doc is provided for legacy purposes, and you should consider usingReact.PureComponentinstead.The
PureRenderMixinmixin predatesReact.PureComponent. This reference doc is provided for legacy purposes, and you should consider usingReact.PureComponentinstead.If your React component's render function renders the same result given the same props and state, you can use this mixin for a performance boost in some cases.
@@ -255,6 +255,11 @@ ++ Higher-Order Components + + + @@ -409,7 +414,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/react-api.html b/docs/react-api.html index b9f1114649..5ffa86ea2c 100644 --- a/docs/react-api.html +++ b/docs/react-api.html @@ -63,7 +63,7 @@ @@ -233,7 +233,7 @@
React.Children.forEach#React.Children.forEach(children, function[(thisArg)])Like
-React.Children.map()but does not return an array.
React.Children.count#@@ -191,7 +191,7 @@Children.count(children) +
React.Children.count#React.Children.count(children)Returns the total number of components in
children, equal to the number of times that a callback passed tomaporforEachwould be invoked.
React.Children.only#@@ -629,7 +634,7 @@React.Children.only(children) @@ -475,6 +475,11 @@ ++ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/react-component.html b/docs/react-component.html index c5d4e270be..012db3e22b 100644 --- a/docs/react-component.html +++ b/docs/react-component.html @@ -63,7 +63,7 @@Note that React may call this method even if the props have not changed, so make sure to compare the current and next values if you only want to handle changes. This may occur when the parent component causes your component to re-render.
-+
componentWillReceiveProps()is not invoked if you just callthis.setState()React doesn't call
componentWillReceivePropswith initial props during mounting. It only calls this method if some of component's props may update. Callingthis.setStategenerally doesn't triggercomponentWillReceiveProps.
shouldComponentUpdate()#@@ -613,7 +618,7 @@shouldComponentUpdate(nextProps, nextState) @@ -459,6 +459,11 @@ ++ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/react-dom-server.html b/docs/react-dom-server.html index 43e162cf0b..16108f210a 100644 --- a/docs/react-dom-server.html +++ b/docs/react-dom-server.html @@ -63,7 +63,7 @@ @@ -235,6 +235,11 @@ ++ Higher-Order Components + + + @@ -389,7 +394,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/react-dom.html b/docs/react-dom.html index 84ca1c26dc..a856e8baf0 100644 --- a/docs/react-dom.html +++ b/docs/react-dom.html @@ -63,7 +63,7 @@ @@ -277,6 +277,11 @@ and should be avoided because future versions of React may render components asy ++ Higher-Order Components + + + @@ -431,7 +436,7 @@ and should be avoided because future versions of React may render components asy![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/react-without-es6.html b/docs/react-without-es6.html index 75fda5adad..2cdd67de7c 100644 --- a/docs/react-without-es6.html +++ b/docs/react-without-es6.html @@ -63,7 +63,7 @@ @@ -144,12 +144,13 @@class SayHello extends React.Component { constructor(props) { super(props); + this.state = {message: 'Hello!'}; // This line is important! this.handleClick = this.handleClick.bind(this); } handleClick() { - alert('Hello!'); + alert(this.state.message); } render() { @@ -164,8 +165,12 @@With
React.createClass(), this is not necessary because it binds all methods:@@ -256,6 +256,11 @@ +var SayHello = React.createClass({ + getInitialState: function() { + return {message: 'Hello!'}; + }, + handleClick: function() { - alert('Hello!'); + alert(this.state.message); }, render: function() { @@ -181,10 +186,14 @@If the boilerplate code is too unattractive to you, you may enable the experimental Class Properties syntax proposal with Babel:
@@ -548,7 +562,7 @@class SayHello extends React.Component { + constructor(props) { + super(props); + this.state = {message: 'Hello!'}; + } // WARNING: this syntax is experimental! // Using an arrow here binds the method: handleClick = () => { - alert('Hello!'); + alert(this.state.message); } render() { @@ -394,6 +403,11 @@ ++ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/react-without-jsx.html b/docs/react-without-jsx.html index 360c2abdac..946907b60c 100644 --- a/docs/react-without-jsx.html +++ b/docs/react-without-jsx.html @@ -63,7 +63,7 @@+ Higher-Order Components + + + @@ -410,7 +415,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/reconciliation.html b/docs/reconciliation.html index 081a3d27e5..2783b5a8e5 100644 --- a/docs/reconciliation.html +++ b/docs/reconciliation.html @@ -63,7 +63,7 @@ @@ -328,6 +328,11 @@ ++ Higher-Order Components + + + @@ -482,7 +487,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/refs-and-the-dom.html b/docs/refs-and-the-dom.html index d57f15303e..8fd66c5761 100644 --- a/docs/refs-and-the-dom.html +++ b/docs/refs-and-the-dom.html @@ -63,7 +63,7 @@ @@ -291,6 +291,11 @@ ++ Higher-Order Components + + + @@ -445,7 +450,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/rendering-elements.html b/docs/rendering-elements.html index b5cde4b45d..50b1646dfe 100644 --- a/docs/rendering-elements.html +++ b/docs/rendering-elements.html @@ -63,7 +63,7 @@ @@ -291,6 +291,11 @@ ++ Higher-Order Components + + + @@ -445,7 +450,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/shallow-compare.html b/docs/shallow-compare.html index 26118b2dea..54d61e51e0 100644 --- a/docs/shallow-compare.html +++ b/docs/shallow-compare.html @@ -63,7 +63,7 @@ @@ -245,6 +245,11 @@ It does this by iterating on the keys of the objects being compared and returnin ++ Higher-Order Components + + + @@ -399,7 +404,7 @@ It does this by iterating on the keys of the objects being compared and returnin![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/state-and-lifecycle.html b/docs/state-and-lifecycle.html index 56235c385f..2018e6be2e 100644 --- a/docs/state-and-lifecycle.html +++ b/docs/state-and-lifecycle.html @@ -63,7 +63,7 @@ @@ -419,7 +419,7 @@This also works for user-defined components:
-<FormattedDate date={this.state.date} />The
+FormattedDatecomponent would receive thedatein its props and wouldn't know whether it came from theClock's state, the props, or was typed by hand:The
FormattedDatecomponent would receive thedatein its props and wouldn't know whether it came from theClock's state, from theClock's props, or was typed by hand:@@ -746,7 +751,7 @@function FormattedDate(props) { return <h2>It is {props.date.toLocaleTimeString()}.</h2>; } @@ -592,6 +592,11 @@ ++ Higher-Order Components + + +![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/test-utils.html b/docs/test-utils.html index 7373068646..7b94fdaf1c 100644 --- a/docs/test-utils.html +++ b/docs/test-utils.html @@ -63,7 +63,7 @@ @@ -437,6 +437,11 @@ ++ Higher-Order Components + + + @@ -591,7 +596,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/thinking-in-react.html b/docs/thinking-in-react.html index f8d81b1be8..ab7568e61d 100644 --- a/docs/thinking-in-react.html +++ b/docs/thinking-in-react.html @@ -63,7 +63,7 @@ @@ -361,6 +361,11 @@ ++ Higher-Order Components + + + @@ -515,7 +520,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/two-way-binding-helpers.html b/docs/two-way-binding-helpers.html index 6f88ae40b8..5f6a6ffd7d 100644 --- a/docs/two-way-binding-helpers.html +++ b/docs/two-way-binding-helpers.html @@ -63,7 +63,7 @@ @@ -314,6 +314,11 @@ ++ Higher-Order Components + + + @@ -468,7 +473,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/typechecking-with-proptypes.html b/docs/typechecking-with-proptypes.html index 3a6f97fd66..dd4fd67bca 100644 --- a/docs/typechecking-with-proptypes.html +++ b/docs/typechecking-with-proptypes.html @@ -63,7 +63,7 @@ @@ -348,6 +348,11 @@ ++ Higher-Order Components + + + @@ -502,7 +507,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/uncontrolled-components.html b/docs/uncontrolled-components.html index 76f774a8c2..e537a8d528 100644 --- a/docs/uncontrolled-components.html +++ b/docs/uncontrolled-components.html @@ -63,7 +63,7 @@ @@ -267,6 +267,11 @@ ++ Higher-Order Components + + + @@ -421,7 +426,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/update.html b/docs/update.html index c00ad2b004..0d68b1cf0f 100644 --- a/docs/update.html +++ b/docs/update.html @@ -63,7 +63,7 @@ @@ -285,6 +285,11 @@ ++ Higher-Order Components + + + @@ -439,7 +444,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/videos-it-IT.html b/docs/videos-it-IT.html index 18aecb27e5..a53aed6f13 100644 --- a/docs/videos-it-IT.html +++ b/docs/videos-it-IT.html @@ -63,7 +63,7 @@ @@ -305,7 +305,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/videos-ko-KR.html b/docs/videos-ko-KR.html index 965a345c28..bccf8e11a4 100644 --- a/docs/videos-ko-KR.html +++ b/docs/videos-ko-KR.html @@ -63,7 +63,7 @@ @@ -306,7 +306,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/videos-zh-CN.html b/docs/videos-zh-CN.html index 2f2a4c08b1..a7fe8c60b7 100644 --- a/docs/videos-zh-CN.html +++ b/docs/videos-zh-CN.html @@ -63,7 +63,7 @@ @@ -305,7 +305,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/docs/web-components.html b/docs/web-components.html index e26f188bfd..029fadc8c0 100644 --- a/docs/web-components.html +++ b/docs/web-components.html @@ -63,7 +63,7 @@ @@ -257,6 +257,11 @@ You will need to manually attach event handlers to handle these events within yo ++ Higher-Order Components + + + @@ -411,7 +416,7 @@ You will need to manually attach event handlers to handle these events within yo![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/downloads/react-15.4.1.zip b/downloads/react-15.4.1.zip new file mode 100644 index 0000000000..c29baf37e1 Binary files /dev/null and b/downloads/react-15.4.1.zip differ diff --git a/feed.xml b/feed.xml index 1ef1f46878..74b3bf0de4 100644 --- a/feed.xml +++ b/feed.xml @@ -379,7 +379,7 @@ I think we should just treat arrays of elements as a frag. This is useful for co <p><center><a target="_blank" href="/react/img/blog/react-50k-mock-full.jpg"><img src="/react/img/blog/react-50k-mock.jpg" width="400" height="410" alt="React website mock" /></a></center></p> -<p>In its earliest days, React benefitted tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.</p> +<p>In its earliest days, React benefited tremendously from feedback, ideas, and technical contributions of early adopters and collaborators all over the company. While it might look like an overnight success in hindsight, the story of React is actually a great example of how new ideas often need to go through several rounds of refinement, iteration, and course correction over a long period of time before reaching their full potential.</p> <p>React's approach to building user interfaces with functional programming principles has changed the way we do things in just a few short years. It goes without saying, but React would be nothing without the amazing open source community that's built up around it!</p> diff --git a/index.html b/index.html index ba32d8e199..84475cd485 100644 --- a/index.html +++ b/index.html @@ -63,7 +63,7 @@ @@ -212,7 +212,7 @@![]()
- Copyright © 2016 Facebook Inc. + Copyright © 2017 Facebook Inc. diff --git a/js/ErrorDecoderComponent.js b/js/ErrorDecoderComponent.js index 0af3bb5a4b..ad46a7e7e6 100644 --- a/js/ErrorDecoderComponent.js +++ b/js/ErrorDecoderComponent.js @@ -140,8 +140,8 @@ var ErrorDecoder = function (_React$Component) { ErrorDecoder.prototype.componentWillMount = function componentWillMount() { var parseResult = parseQueryString(); if (parseResult != null) { - var code = parseResult[0]; - var args = parseResult[1]; + var code = parseResult[0], + args = parseResult[1]; if (errorMap[code]) { this.setState({ diff --git a/js/react-dom.js b/js/react-dom.js index f434adb0e8..b25fd38725 100644 --- a/js/react-dom.js +++ b/js/react-dom.js @@ -1,15 +1,15 @@ /** - * ReactDOM v15.4.0 + * ReactDOM v15.4.1 */ ;(function(f) { // CommonJS if (typeof exports === "object" && typeof module !== "undefined") { - f(require('react')); + module.exports = f(require('react')); // RequireJS } else if (typeof define === "function" && define.amd) { - require(['react'], f); + define(['react'], f); //