Skip to content
Merged
Show file tree
Hide file tree
Changes from 101 commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
444896e
Initial draft for 16.3 release blog
bvaughn Feb 5, 2018
141de66
Wording changes in response to PR feedback
bvaughn Feb 5, 2018
ce57928
Added entry for createRef API
bvaughn Feb 6, 2018
da29d89
Added note about string ref API to strict mode section
bvaughn Feb 6, 2018
a55480b
Small wording nit
bvaughn Feb 6, 2018
935d2a1
Minor edits in response to PR feedback
bvaughn Feb 6, 2018
ab62e88
Formatted example
bvaughn Feb 7, 2018
08d444e
Wordsmithing in response to PR feedback
bvaughn Feb 12, 2018
5a1d653
Incorporated Sophie's PR feedback
bvaughn Feb 13, 2018
8494428
Added example of before/after context API
bvaughn Feb 13, 2018
c08533a
Removed context-before example
bvaughn Feb 13, 2018
33ff167
Wordsmith nit
bvaughn Feb 13, 2018
c09a284
Added React.createRef doc
trueadm Feb 22, 2018
ee78358
address feedback
trueadm Feb 22, 2018
b049931
revised content as per PR feedback
trueadm Mar 4, 2018
9bc1932
updated line numbers
trueadm Mar 4, 2018
6627687
Describe what a ref is at the top of the doc
Mar 4, 2018
0e7243f
Merge intro paragraphs
Mar 4, 2018
c07a6b0
Merge pull request #1 from alexkrolick/create-ref-patch
trueadm Mar 4, 2018
7b02740
Create "Accessing refs" section above specific examples
Mar 4, 2018
d7b34d4
Merge pull request #2 from alexkrolick/create-ref-patch-2
trueadm Mar 4, 2018
8075ce2
Make the callback example more similar to the new API
Mar 4, 2018
96fe82c
Declare setRef method outside render
alexkrolick Mar 6, 2018
96b10a7
Grammar
alexkrolick Mar 6, 2018
962ef9a
Highlight deprecation notice
alexkrolick Mar 6, 2018
4b939d2
~~All things considered~~
alexkrolick Mar 6, 2018
04c7f16
Wording
alexkrolick Mar 6, 2018
b1adba0
Recommend old API when applicable
alexkrolick Mar 6, 2018
9b869fa
Update leading sentence
alexkrolick Mar 6, 2018
566406e
Add docs for new Context API (R16.3)
alexkrolick Mar 6, 2018
a89e6b8
Added link to context API docs
bvaughn Mar 6, 2018
5e0901d
Merge pull request #3 from alexkrolick/create-ref-patch-3
trueadm Mar 6, 2018
3f304b9
Merge pull request #4 from alexkrolick/create-ref-patch4
trueadm Mar 6, 2018
f6e5d65
Fixed off-by-one line highlights.
bvaughn Mar 7, 2018
6e35810
Merge branch 'master' into 16.3-release-blog-post
bvaughn Mar 7, 2018
6a1ba97
Moved 16.3 release date arbitrarily forward
bvaughn Mar 7, 2018
1de2e33
Fixed links
bvaughn Mar 7, 2018
c7a61e6
Imported StrictMode docs (and examples) from PR #596
bvaughn Mar 7, 2018
fecb153
Merge pull request #1 from trueadm/create-ref
bvaughn Mar 7, 2018
866ef01
Prettier
bvaughn Mar 7, 2018
12d7c16
Updated createRef 'value' attributes to 'current'
bvaughn Mar 14, 2018
e5bf594
Unnest callback ref example code
alexkrolick Mar 15, 2018
2f97f48
Fixed docs
bvaughn Mar 15, 2018
a357b64
Added React.forwardRef to 16.3 release blog post
bvaughn Mar 15, 2018
a937c46
Typo fixes
bvaughn Mar 15, 2018
201fcad
Added React.forwardRef to API and docs
bvaughn Mar 16, 2018
2b1de01
Rebuild Netlify
bvaughn Mar 16, 2018
22d0ec1
Updated forwardRef example to use named function
bvaughn Mar 16, 2018
fe033f6
Added StrictMode to docs sidenav
bvaughn Mar 16, 2018
f14f147
Renamed ref in example
bvaughn Mar 18, 2018
5d5a5d2
StrictMode title => Strict Mode
bvaughn Mar 19, 2018
2ead10e
Update nav
gaearon Mar 19, 2018
29d6592
Update React.Component reference to show deprecations and new lifecycles
bvaughn Mar 20, 2018
0780f72
Reorganize examples & legacy docs
alexkrolick Mar 21, 2018
a5022da
Add in-page TOC
alexkrolick Mar 21, 2018
fe3d0a4
Typo
alexkrolick Mar 21, 2018
808e5bd
Rephrase and reorganize
alexkrolick Mar 21, 2018
de22379
Syntax tweaks
alexkrolick Mar 21, 2018
291b2fd
Wording tweaks
alexkrolick Mar 21, 2018
6aa1995
Add solution to motivation problem
alexkrolick Mar 21, 2018
7c6688c
Highlight createContext()
alexkrolick Mar 21, 2018
b49f99b
Highlight whole createContext() call
alexkrolick Mar 21, 2018
dbce488
Merge pull request #3 from alexkrolick/new-context-api
bvaughn Mar 22, 2018
2f9b77a
16.4 -> 16.x
bvaughn Mar 22, 2018
e9ae68f
remove confusing {}
alexkrolick Mar 23, 2018
53d604f
~deprecated~ legacy
alexkrolick Mar 23, 2018
fec6d6c
Add mutliple contexts example
alexkrolick Mar 23, 2018
7b5764f
Add ref forwarding, lifecycle examples
alexkrolick Mar 23, 2018
0d32f18
Kill highlight
alexkrolick Mar 23, 2018
7db107b
+ "default value" comment
alexkrolick Mar 23, 2018
da091e6
Add note about how changes are determined
alexkrolick Mar 23, 2018
6eb29a1
Combine basic examples
alexkrolick Mar 23, 2018
9f54997
Update highlights
alexkrolick Mar 23, 2018
4e1282e
Add to "when to use context"
alexkrolick Mar 23, 2018
f588bd6
Update "legacy" wording
alexkrolick Mar 23, 2018
ccc1f26
Replace "deprecated" with "legacy" for now
alexkrolick Mar 23, 2018
3af89c9
Merge pull request #4 from alexkrolick/context-tweaks
bvaughn Mar 23, 2018
01c2691
Replaced cWRP in forwardRef example with cDU
bvaughn Mar 23, 2018
f5d5139
Formatted a Note
bvaughn Mar 23, 2018
5864093
Updated context-in-lifecycles example
bvaughn Mar 23, 2018
d66d3a2
Updated TODO for later
bvaughn Mar 23, 2018
ef23c49
Updated multi-context example to show more indirection
bvaughn Mar 23, 2018
b25276a
Updated forward-refs example to use class component
bvaughn Mar 23, 2018
c41bb29
Added DevTools name consideration to forwardRef examples
bvaughn Mar 23, 2018
1ead060
17 -> future version
alexkrolick Mar 23, 2018
d58c892
+ "same algo"
alexkrolick Mar 23, 2018
e689824
Add notes about composing multiple contexts
alexkrolick Mar 23, 2018
509b126
Explain context in lifecycle a bit more
alexkrolick Mar 23, 2018
fe84e09
Explain why you need forwardRef
alexkrolick Mar 23, 2018
9e4442a
typo
alexkrolick Mar 23, 2018
3c44882
Use function keyword
alexkrolick Mar 23, 2018
f9225e2
Remove propTypes
alexkrolick Mar 23, 2018
fb8e9e8
kill class props
alexkrolick Mar 23, 2018
6919801
Use functional component
alexkrolick Mar 23, 2018
c9d50e3
Remove lib link
alexkrolick Mar 23, 2018
7ac0712
Updated 16.3 blog post to account for getSnapshotBeforeUpdate lifecycle
bvaughn Mar 23, 2018
920b4f4
Replace divs with some fake components
alexkrolick Mar 23, 2018
349446d
Add caveats section
alexkrolick Mar 23, 2018
b0e8604
Prettier
alexkrolick Mar 23, 2018
8437e37
Fix syntax
alexkrolick Mar 23, 2018
587ad93
Merge pull request #5 from alexkrolick/16.3-release-blog-post
bvaughn Mar 23, 2018
f11a149
Added DevTools naming consideration to React.forwardRef reference doc…
bvaughn Mar 24, 2018
bd06bbc
Added context HOC example to reference
bvaughn Mar 24, 2018
b7b97c0
Merge branch 'master' into 16.3-release-blog-post
bvaughn Mar 27, 2018
6d77836
Linked to async blog post
bvaughn Mar 27, 2018
e5cf31a
Renamed blog post
bvaughn Mar 27, 2018
a29098e
Merge branch 'master' into 16.3-release-blog-post
bvaughn Mar 28, 2018
57eb7cc
Tweaked message about what goes into state
bvaughn Mar 29, 2018
28b2b76
Tweaked state-and-lifecycle wording more
bvaughn Mar 29, 2018
691cd45
Added inline child function caveat to Context docs
bvaughn Mar 29, 2018
032576c
Prettier
bvaughn Mar 29, 2018
797a792
Revert "Prettier"
bvaughn Mar 29, 2018
3a36a40
Revert "Added inline child function caveat to Context docs"
bvaughn Mar 29, 2018
e5ca13e
Cross-link to async update post
bvaughn Mar 29, 2018
992a756
Missing 'we'
bvaughn Mar 29, 2018
5a587d1
Tweaked link to Context API
bvaughn Mar 29, 2018
ac1d767
Fixed link
bvaughn Mar 29, 2018
aa9810f
Fixed some links and improved a recommendation
bvaughn Mar 29, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions content/blog/2018-03-20-react-v-16-3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: "React v16.3.0: New lifecycles and context API"
author: [bvaughn]
---

This release includes an official context API, new class component lifecycles, a new `StrictMode` component, a new ergonomic ref API, and a ref-forwarding API!

For the past few months, the React team has been working on support for [asynchronous rendering](/blog/2018/03/01/sneak-peek-beyond-react-16.html). We are excited about the new features it will enable.

We've also learned that some long-term changes will be required to the way we write React components. However, we respect [semver](https://semver.org/) and **will not ship breaking changes in a minor version**!

Read on to learn more about the release.

## Official Context API

For many years, React has offered an experimental API for context. Although it was a powerful tool, its use was discouraged because of inherent problems in the API, and because we always intended to replace the experimental API with a better one.

Version 16.3 introduces a new context API that is more efficient and supports both static type checking and deep updates.

> **Note**
>
> The old context API will keep working for all React 16.x releases, so you will have time to migrate.

Here is an example illustrating how you might inject a "theme" using the new context API:
`embed:16-3-release-blog-post/context-example.js`

[Learn more about the new context API here.](/docs/context.html#api)

## `createRef` API

Previously, React provided two ways of managing refs: the legacy string ref API and the callback API. Although the string ref API was the more convenient of the two, it had [several downsides](https://github.com/facebook/react/issues/1373) and so our official recommendation was to use the callback form instead.

Version 16.3 adds a new option for managing refs that offers the convenience of a string ref without any of the downsides:
`embed:16-3-release-blog-post/create-ref-example.js`

> **Note:**
>
> Callback refs will continue to be supported in addition to the new `createRef` API.
>
> You don't need to replace callback refs in your components. They are slightly more flexible, so they will remain as an advanced feature.

[Learn more about the new `createRef` API here.](/docs/refs-and-the-dom.html)

## `forwardRef` API

[Higher-order components](/docs/higher-order-components.html) (or HOCs) are a common way to reuse code between components. Building on the theme context example from above, we might create an HOC that injects the current "theme" as a prop:

`embed:16-3-release-blog-post/hoc-theme-example.js`

We can use the above HOC to wire components up to the theme context without having to use `ThemeContext` directly. For example:

`embed:16-3-release-blog-post/fancy-button-example.js`

HOCs typically [pass props through](/docs/higher-order-components.html#convention-pass-unrelated-props-through-to-the-wrapped-component) to the components they wrap. Unfortunately, [refs are not passed through](/docs/higher-order-components.html#refs-arent-passed-through). This means that we can't attach a ref to `FancyButton` if we use `FancyThemedButton`- so there's no way for us to call `focus()`.

The new `forwardRef` API solves this problem by providing a way for us to intercept a `ref` and forward it as a normal prop:
`embed:16-3-release-blog-post/forward-ref-example.js`

## Component Lifecycle Changes

React's class component API has been around for years with little change. However, as we add support for more advanced features (such as [error boundaries](/docs/react-component.html#componentdidcatch) and the upcoming [async rendering mode](/blog/2018/03/01/sneak-peek-beyond-react-16.html)) we stretch this model in ways that it was not originally intended.

For example, with the current API, it is too easy to block the initial render with non-essential logic. In part this is because there are too many ways to accomplish a given task, and it can be unclear which is best. We've observed that the interrupting behavior of error handling is often not taken into consideration and can result in memory leaks (something that will also impact the upcoming async rendering mode). The current class component API also complicates other efforts, like our work on [prototyping a React compiler](https://twitter.com/trueadm/status/944908776896978946).

Many of these issues are exacerbated by a subset of the component lifecycles (`componentWillMount`, `componentWillReceiveProps`, and `componentWillUpdate`). These also happen to be the lifecycles that cause the most confusion within the React community. For these reasons, we are going to deprecate those methods in favor of better alternatives.

We recognize that this change will impact many existing components. Because of this, the migration path will be as gradual as possible, and will provide escape hatches. (At Facebook, we maintain more than 50,000 React components. We depend on a gradual release cycle too!)

> **Note:**
>
> Deprecation warnings will be enabled with a future 16.x release, **but the legacy lifecycles will continue to work until version 17**.
>
> Even in version 17, it will still be possible to use them, but they will be aliased with an "UNSAFE_" prefix to indicate that they might cause issues. We have also prepared an [automated script to rename them](https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles) in existing code.

In addition to deprecating unsafe lifecycles, we are also adding a couple of new lifecyles:
* [`getDerivedStateFromProps`](/docs/react-component.html#static-getderivedstatefromprops) is being added as a safer alternative to the legacy `componentWillReceiveProps`.
* [`getSnapshotBeforeUpdate`](/docs/react-component.html#getsnapshotbeforeupdate) is being added to support safely reading properties from e.g. the DOM before updates are made.

[Learn more about these lifecycle changes here.](#TODO-link-to-update-on-async-blog-post)

## `StrictMode` Component

`StrictMode` is a tool for highlighting potential problems in an application. Like `Fragment`, `StrictMode` does not render any visible UI. It activates additional checks and warnings for its descendants.

> **Note:**
>
> `StrictMode` checks are run in development mode only; _they do not impact the production build_.

Although it is not possible for strict mode to catch all problems (e.g. certain types of mutation), it can help with many. If you see warnings in strict mode, those things will likely cause bugs for async rendering.

In version 16.3, `StrictMode` helps with:
* Identifying components with unsafe lifecycles
* Warning about legacy string ref API usage
* Detecting unexpected side effects

Additional functionality will be added with future releases of React.

[Learn more about the `StrictMode` component here.](/docs/strict-mode.html)
248 changes: 79 additions & 169 deletions content/docs/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,220 +4,130 @@ title: Context
permalink: docs/context.html
---

> Note:
>
> `React.PropTypes` has moved into a different package since React v15.5. Please use [the `prop-types` library instead](https://www.npmjs.com/package/prop-types) to define `contextTypes`.
>
>We provide [a codemod script](/blog/2017/04/07/react-v15.5.0.html#migrating-from-react.proptypes) to automate the conversion.
Context provides a way to pass data through the component tree without having to pass props down manually at every level.

With React, it's easy to track the flow of data through your React components. When you look at a component, you can see which props are being passed, which makes your apps easy to reason about.
In a typical React application, data is passed top-down (parent to child) via props, but this can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like this between components without having to explicitly pass a prop through every level of the tree.

In some cases, you want to pass data through the component tree without having to pass the props down manually at every level.
You can do this directly in React with the powerful "context" API.
- [When to Use Context](#when-to-use-context)
- [API](#api)
- [React.createContext](#reactcreatecontext)
- [Provider](#provider)
- [Consumer](#consumer)
- [Examples](#examples)
- [Static Context](#static-context)
- [Dynamic Context](#dynamic-context)
- [Consuming Multiple Contexts](#consuming-multiple-contexts)
- [Accessing Context in Lifecycle Methods](#accessing-context-in-lifecycle-methods)
- [Forwarding Refs to Context Consumers](#forwarding-refs-to-context-consumers)
- [Caveats](#caveats)
- [Legacy API](#legacy-api)

> Note:
>
> A [new, safe version of context](https://github.com/reactjs/rfcs/blob/master/text/0002-new-version-of-context.md) is under development for the upcoming 16.3 release.

## When to Use Context

## Why Not To Use Context
Context is designed to share data that can be considered "global" for a tree of React components, such as the current authenticated user, theme, or preferred language. For example, in the code below we manually thread through a "theme" prop in order to style the Button component:

The vast majority of applications do not need to use context.
`embed:context/motivation-problem.js`

If you want your application to be stable, don't use context. It is an experimental API and it is likely to break in future releases of React.
Using context, we can avoid passing props through intermediate elements:

If you aren't familiar with state management libraries like [Redux](https://github.com/reactjs/redux) or [MobX](https://github.com/mobxjs/mobx), don't use context. For many practical applications, these libraries and their React bindings are a good choice for managing state that is relevant to many components. It is far more likely that Redux is the right solution to your problem than that context is the right solution.
`embed:context/motivation-solution.js`

If you're still learning React, don't use context. There is usually a better way to implement functionality just using props and state.
> Note
>
> Don't use context just to avoid passing props a few levels down. Stick to cases where the same data needs to accessed in many components at multiple levels.

If you insist on using context despite these warnings, try to isolate your use of context to a small area and avoid using the context API directly when possible so that it's easier to upgrade when the API changes.
## API

## How To Use Context
### `React.createContext`

Suppose you have a structure like:
```js
const {Provider, Consumer} = React.createContext(defaultValue);
```

```javascript
class Button extends React.Component {
render() {
return (
<button style={{background: this.props.color}}>
{this.props.children}
</button>
);
}
}
Creates a `{ Provider, Consumer }` pair.

class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button color={this.props.color}>Delete</Button>
</div>
);
}
}
Optionally accepts a default value to be passed to Consumers without a Provider ancestor.

class MessageList extends React.Component {
render() {
const color = "purple";
const children = this.props.messages.map((message) =>
<Message text={message.text} color={color} />
);
return <div>{children}</div>;
}
}
```
### `Provider`

In this example, we manually thread through a `color` prop in order to style the `Button` and `Message` components appropriately. Using context, we can pass this through the tree automatically:

```javascript{6,13-15,21,28-30,40-42}
import PropTypes from 'prop-types';

class Button extends React.Component {
render() {
return (
<button style={{background: this.context.color}}>
{this.props.children}
</button>
);
}
}

Button.contextTypes = {
color: PropTypes.string
};

class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button>Delete</Button>
</div>
);
}
}

class MessageList extends React.Component {
getChildContext() {
return {color: "purple"};
}

render() {
const children = this.props.messages.map((message) =>
<Message text={message.text} />
);
return <div>{children}</div>;
}
}

MessageList.childContextTypes = {
color: PropTypes.string
};
```js
<Provider value={/* some value */}>
```

By adding `childContextTypes` and `getChildContext` to `MessageList` (the context provider), React passes the information down automatically and any component in the subtree (in this case, `Button`) can access it by defining `contextTypes`.
A React component that allows Consumers to subscribe to context changes.

If `contextTypes` is not defined, then `context` will be an empty object.
Accepts a `value` prop to be passed to Consumers that are descendants of this Provider. One Provider can be connected to many Consumers. Providers can be nested to override values deeper within the tree.

## Parent-Child Coupling
### `Consumer`

Context can also let you build an API where parents and children communicate. For example, one library that works this way is [React Router V4](https://reacttraining.com/react-router):
```js
<Consumer>
{value => /* render something based on the context value */}
</Consumer>
```

```javascript
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
A React component that subscribes to context changes.

const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
Requires a [function as a child](/docs/render-props.html#using-props-other-than-render). The function receives the current context value and returns a React node. All consumers are re-rendered whenever the Provider value changes. Changes are determined by comparing the new and old values using the same algorithm as [`Object.is`](developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#Description). (This can cause some issues when passing objects as `value`: see [Caveats](#caveats).)

<hr />
> Note
>
> For more information about this pattern, see [render props](/docs/render-props.html).

<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
);
```
## Examples

By passing down some information from the `Router` component, each `Link` and `Route` can communicate back to the containing `Router`.
### Dynamic Context

Before you build components with an API similar to this, consider if there are cleaner alternatives. For example, you can pass entire React components as props if you'd like to.
A more complex example with dynamic values for the theme:

## Referencing Context in Lifecycle Methods
**theme-context.js**
`embed:context/theme-detailed-theme-context.js`

If `contextTypes` is defined within a component, the following [lifecycle methods](/docs/react-component.html#the-component-lifecycle) will receive an additional parameter, the `context` object:
**themed-button.js**
`embed:context/theme-detailed-themed-button.js`

- [`constructor(props, context)`](/docs/react-component.html#constructor)
- [`componentWillReceiveProps(nextProps, nextContext)`](/docs/react-component.html#componentwillreceiveprops)
- [`shouldComponentUpdate(nextProps, nextState, nextContext)`](/docs/react-component.html#shouldcomponentupdate)
- [`componentWillUpdate(nextProps, nextState, nextContext)`](/docs/react-component.html#componentwillupdate)
**app.js**
`embed:context/theme-detailed-app.js`

> Note:
>
> As of React 16, `componentDidUpdate` no longer receives `prevContext`.
### Consuming Multiple Contexts

## Referencing Context in Stateless Functional Components
To keep context re-rendering fast, React needs to make each context consumer a separate node in the tree.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a paragraph there explaining that to keep context re-rendering fast, React needs to make each context consumer a separate node in the tree. Because we'll get the question.

Stateless functional components are also able to reference `context` if `contextTypes` is defined as a property of the function. The following code shows a `Button` component written as a stateless functional component.
`embed:context/multiple-contexts.js`

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After this example, we should point out that if two or more context values are often used together, you might want to consider creating your own render prop component that provides both. Then link to this utility as a simple way to do it.

```javascript
import PropTypes from 'prop-types';
If two or more context values are often used together, you might want to consider creating your own render prop component that provides both.

const Button = ({children}, context) =>
<button style={{background: context.color}}>
{children}
</button>;
### Accessing Context in Lifecycle Methods

Button.contextTypes = {color: PropTypes.string};
```
Accessing values from context in lifecycle methods is a relatively common use case. Instead of adding context to every lifecycle method, you just need to pass it as a prop, and then work with it just like you'd normally work with a prop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, needs an intro before the example. Explain that this is a relatively common use case. And that instead of adding context to every lifecycle method, you just need to pass it as a prop, and then work with it just like you'd normally work with a prop.

## Updating Context
`embed:context/lifecycles.js`

Don't do it.
### Forwarding Refs to Context Consumers

React has an API to update context, but it is fundamentally broken and you should not use it.
One issue with the render prop API is that refs don't automatically get passed to wrapped elements. To get around this, use `React.forwardRef`:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to briefly explain the problem with previous example here.

The `getChildContext` function will be called when the state or props changes. In order to update data in the context, trigger a local state update with `this.setState`. This will trigger a new context and changes will be received by the children.
**fancy-button.js**
`embed:context/forwarding-refs-fancy-button.js`

```javascript
import PropTypes from 'prop-types';
**app.js**
`embed:context/forwarding-refs-app.js`

class MediaQuery extends React.Component {
constructor(props) {
super(props);
this.state = {type:'desktop'};
}
## Caveats
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before Caveats, I think we should also add a section that explains how to create a higher order component for consuming context. This is a common sentiment and I think we should proactively address it: https://twitter.com/DankoKozar/status/977469702204162048?s=20

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Context comes before the Higher-Order Components reference page, but I'll cross link.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, cyclical dependencies are pretty much unavoidable in the "Advanced" section


getChildContext() {
return {type: this.state.type};
}
Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider's parent re-renders. For example, the code below will re-render all consumers every time the Provider re-renders because a new object is always created for `value`:

componentDidMount() {
const checkMediaQuery = () => {
const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
if (type !== this.state.type) {
this.setState({type});
}
};
`embed:context/reference-caveats-problem.js`

window.addEventListener('resize', checkMediaQuery);
checkMediaQuery();
}

render() {
return this.props.children;
}
}
To get around this, lift the value into the parent's state:

MediaQuery.childContextTypes = {
type: PropTypes.string
};
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There needs to be a section on how to reference context in lifecycle methods. It can be deduced from this article but people will initially feel it's gross so we need to be explicit that it's a recommended pattern. Additionally it's important to show how it works with ref forwarding.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should also be an explanation on how to consume more than one context. Even if it links to a gist.

`embed:context/reference-caveats-solution.js`

## Legacy API
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before "Legacy API", we need to add a "Caveats" section.

There, we should mention that pattern like <Provider value={{ something: 'something' }}> re-renders all consumers every time the provider parent re-renders because the value object is referentially different every time. If you didn't intend this, put the value into the parent component's state so that it doesn't change unintentionally between re-renders.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to put this in the Consumer API section?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe. What do you think? I generally prefer to separate "minimal necessary" information to use the API from all the details (that they user won't bump into later on), but maybe it's okay to do in one place. The main reason I suggested a separate section is because I wanted to have a "good" and "bad" example (even if they're one liners), and I felt it would they would steal the focus from the API reference if we put them there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, how about linking to Caveats/Gotchas after mentioning the Object.is comparison?

Copy link
Member

@gaearon gaearon Mar 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good


The problem is, if a context value provided by component changes, descendants that use that value won't update if an intermediate parent returns `false` from `shouldComponentUpdate`. This is totally out of control of the components using context, so there's basically no way to reliably update the context. [This blog post](https://medium.com/@mweststrate/how-to-safely-use-react-context-b7e343eff076) has a good explanation of why this is a problem and how you might get around it.
> Note
>
> React previously shipped with an experimental context API. The old API will be supported in all 16.x releases, but applications using it should migrate to the new version. The legacy API will be removed in a future major React version. Read the [legacy context docs here](/docs/legacy-context.html).

Loading