Skip to content

Add docs for new Context API #665

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from

Conversation

alexkrolick
Copy link
Collaborator

@alexkrolick alexkrolick commented Mar 6, 2018

@reactjs-bot
Copy link

reactjs-bot commented Mar 6, 2018

Deploy preview for reactjs ready!

Built with commit b49f99b

https://deploy-preview-665--reactjs.netlify.com

Copy link
Contributor

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

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

Some high-level thoughts about organization.

Thanks for kicking off this effort!


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.
## Experimental API (Deprecated in React 16.3)
Copy link
Contributor

@bvaughn bvaughn Mar 20, 2018

Choose a reason for hiding this comment

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

Maybe this could be broken out into its own "Legacy context" page (e.g. content/docs/legacy-context.md) that we link to from this page- but we don't show on the side bar anywhere?


## Using Context

Here is an example illustrating how you might inject a "theme" using context:
Copy link
Contributor

@bvaughn bvaughn Mar 20, 2018

Choose a reason for hiding this comment

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

I prefer the introductory sequence from the old "How to Use Context" section more because of how it setup the problem. "Let's say you have this code and you want to do X. Here's how you could use the context API to do this." rather than "Here's a code snippet"

I would also suggesting putting this down under the "Typical Usage" header. I think the API should be first on this page.

Copy link
Collaborator Author

@alexkrolick alexkrolick Mar 20, 2018

Choose a reason for hiding this comment

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

I think it's confusing how the old example leads with a large codeblock illustrating non-context APIs. Maybe we can invert the order to highlight the context way before the prop-drilling way?

Moving the API section to the top makes sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we could maybe make the initial code block shorter, but I think it's useful to present APIs in the form of "Here is a scenario. How would you solve it? You can solve it using this API."

Also reduce spacing between ul/li tags
@@ -336,7 +336,7 @@ const sharedStyles = {
},

'& li': {
marginTop: 20,
marginTop: 10,
Copy link
Collaborator Author

@alexkrolick alexkrolick Mar 21, 2018

Choose a reason for hiding this comment

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

Reduces spacing between list elements:

After:
image

Before:
image

Don't need to merge this, but probably would want to kill the table of contents links if we keep the larger padding.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it looks nice.

@alexkrolick
Copy link
Collaborator Author

@bvaughn broke out legacy-context.md and reintroduced the props drilling example under "Motivation"

Copy link
Contributor

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

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

Left some thoughts! Some nits and some suggestions.

Thanks!

### `React.createContext`

```js
const {Provider, Consumer} = React.createContext([default]);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why [default] ? (Why the array syntax?) Suggestion:

const {Provider, Consumer} = React.createContext(defaultValue);

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was thinking [] indicated optional arguments. Replacing it with a text note is fine; it's not a real type signature or anything.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha. I don't think thats' what "[]" implies to me. 👍


Creates a `{ Provider, Consumer }` pair.

Takes one argument, the default context that Consumers will receive when they don't have a matching Provider.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

Accepts an optional default value to be passed to Consumers without a Provider ancestor.


A React component that allows Consumers to subscribe to context changes.

Takes one prop, `value`, which will be passed to the [render prop](/docs/render-props.html) of child Consumers for the matching context anywhere in the component tree. One Provider can be connected to many Consumers.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

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.

You can do this directly in React with the powerful "context" API.
A React component that subscribes to context changes.

Takes a function as the `children` prop that receives the `value` prop of the matching Provider. This function will be called whenever the Provider's value is updated.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion:

Requires a function as a child. This function receives the current context value and returns a React node. This function will be called whenever the Provider's value is updated.

@@ -0,0 +1,42 @@
const defaultTheme = 'light';
// highlight-next-line
const ThemeContext = React.createContext(defaultTheme);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Maybe get rid of defaultTheme variable in favor of a comment?

// Initial context with a default value of "light" (theme)
const ThemeContext = React.createContext('light');

state = {
theme: {
highlight: 'blue',
accent: 'purple',
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: It's also a little weird that we have a default value and state with the same value. People might not understand why default value exists if we always do this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What's a good application use case for the default value? The RFC example just says "to ensure type correctness".

Copy link
Contributor

Choose a reason for hiding this comment

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

That's a good observation. I wasn't considering the type-correctness angle. 👍

I was thinking it would be nice for the docs to highlight, in one of the examples, that the default value gets passed to a Consumer if there is no Provider ancestor.

The Message component must take `color` as as prop to pass it to the
Button. Using context, the Button could connect to the color context
on its own.
*/}
Copy link
Contributor

Choose a reason for hiding this comment

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

This block comment within JSX does not read very well. Move it into the render function as just inline comments?


Suppose you have a structure like:
Context is designed to relieve the pain of passing props down through a deeply nested component tree. For example, in the code below we manually thread through a color prop in order to style the Button and Message components. Using context, we can avoid passing props through intermediate elements.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm still not a fan of this sequencing. We show motivation after we show usage examples. That feels backwards to me. I think it would be better to present a problem, and then how to solve it using Context. Step by step.

permalink: docs/legacy-context.html
---

> This API is deprecated as of React 16.3.
Copy link
Contributor

Choose a reason for hiding this comment

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

This should clarify that the feature will be removed in 17.

Suggestion>

The legacy API has been deprecated and will be removed in version 17. Instead, use the new context API introduced with version 16.3.

The legacy API will continue working for all 16.x releases.


## How To Use Context

> This section documents a deprecated API. See the [new API](/docs/context.html).
Copy link
Contributor

Choose a reason for hiding this comment

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

I think these notes are pretty redundant with the one at the head of the page. Probably can remove them?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Probably so. My concern is that it's a long page and someone might get a direct link to a section without noticing the deprecation warning.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's possible. Definitely seems redundant for the first section though, since the two notes are only like 50 pixels apart. I don't feel as strongly about the following sections.

- Move Motivation to top @bvaughn
- Copy in some Motivation text from the RFC for the intro para
- Update examples
  - Remove state from simple example
  - Remove "random color" example;
  just toggle a theme variable instead
- Update highlights
@bvaughn
Copy link
Contributor

bvaughn commented Mar 21, 2018

Looks like CI is saying Prettier needs to be run.

Copy link
Contributor

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

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

Left some more thoughts. Overall I'm digging the changes.

WRT the redundant deprecation notices on the legacy context page, I don't mind them as much at a second glance. They're probably fine.


## Why Not To Use Context
Typically, data in a React application is passed top-down (parent to child) via props. But sometimes it's useful to pass values through multiple levels without adding props to every intermediate component. Examples include a language preference, or a UI theme. Many components may rely on those but you don't want to have to pass a locale prop and a theme prop through every level of the tree.
Copy link
Contributor

Choose a reason for hiding this comment

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

This paragraph feels like it ends a bit prematurely. Maybe we can close by reiterating the opening line?

Wording suggestions:

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.

- [Examples](#examples)
- [Static Context](#static-context)
- [Dynamic Context](#dynamic-context)
- [Legacy API](#legacy-api)
Copy link
Contributor

Choose a reason for hiding this comment

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

I like this table of contents 👍


If you're still learning React, don't use context. There is usually a better way to implement functionality just using props and state.
Context is designed to relieve the pain of passing props down through a deeply nested component tree. For example, in the code below we manually thread through a color prop in order to style the Button and Message components. Using context, we can avoid passing props through intermediate elements.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I would move the "Using context, we can avoid passing props through intermediate elements." sentence to below the coding example, so it's clear that the example isn't showing what context can do.


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.
`embed:context/motivation.js`
Copy link
Contributor

Choose a reason for hiding this comment

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

It still feels wrong to me to have a "motivation" section that does not show how to "fix" the problem we introduce.

- [`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)
Requires a [function as a child](/docs/render-props.html#using-props-other-than-render). This function receives the current context value and returns a React node, and will be called whenever the Provider's value is updated.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the last sentence is a bit too long. Suggestion:

Requires a function as a child. This function receives the current context value and returns a React node. It will be called whenever the Provider's value is updated.

render() {
// The ThemedButton button inside the ThemeProvider
// uses the dark theme while the one outside uses the
// default light theme
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the changes to this example 👍

@@ -0,0 +1,30 @@
import ThemeContext, {themes} from './theme-context';
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we should show a mixed import like this.

Maybe we can import themes from a separate themes.js file? Or change theme-context to remove the default export.

</ThemeContext.Provider>
);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I like the changes to the theme example as well.

@@ -336,7 +336,7 @@ const sharedStyles = {
},

'& li': {
marginTop: 20,
marginTop: 10,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it looks nice.

@alexkrolick
Copy link
Collaborator Author

Thanks for the review @bvaughn. Added the solution to the motivation problem. I think the highlights emphasize the benefits pretty well.

@bvaughn
Copy link
Contributor

bvaughn commented Mar 22, 2018

You're welcome, @alexkrolick. Thanks for owning this change! It's a big help for the upcoming release.

@bvaughn
Copy link
Contributor

bvaughn commented Mar 22, 2018

I'd like to merge this branch into the bvaughn:16.3-release-blog-post branch (PR #587) so these docs can be released with the other 16.3 stuff. That cool with you?

@alexkrolick
Copy link
Collaborator Author

Yep: bvaughn#3

@bvaughn
Copy link
Contributor

bvaughn commented Mar 22, 2018

Thanks!

BetterZxx pushed a commit to BetterZxx/react.dev that referenced this pull request Mar 21, 2023
…nto Chinese (reactjs#665)

* fix: correct some spelling mistakes in handling-events.md

* [Beta]: docs(cn): translate learn/manipulating-the-dom-with-refs.md

* Update beta/src/pages/learn/manipulating-the-dom-with-refs.md

Co-authored-by: ZhangDaZongWei <[email protected]>

* Update beta/src/pages/learn/manipulating-the-dom-with-refs.md

Co-authored-by: ZhangDaZongWei <[email protected]>

* resolve review suggestions from ZhangDaZongWei

* change some strange translations

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* Update beta/src/content/learn/manipulating-the-dom-with-refs.md

Co-authored-by: TimLi <[email protected]>

* remove extra spaces

---------

Co-authored-by: ZhangDaZongWei <[email protected]>
Co-authored-by: Xavi Lee <[email protected]>
Co-authored-by: TimLi <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants