Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 6 additions & 6 deletions src/content/learn/managing-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -697,11 +697,11 @@ Read **[Extracting State Logic into a Reducer](/learn/extracting-state-logic-int

</LearnMore>

## Passing data deeply with context {/*passing-data-deeply-with-context*/}
## Passing data deeply with Context {/*passing-data-deeply-with-context*/}

Usually, you will pass information from a parent component to a child component via props. But passing props can become inconvenient if you need to pass some prop through many components, or if many components need the same information. Context lets the parent component make some information available to any component in the tree below it—no matter how deep it is—without passing it explicitly through props.

Here, the `Heading` component determines its heading level by "asking" the closest `Section` for its level. Each `Section` tracks its own level by asking the parent `Section` and adding one to it. Every `Section` provides information to all components below it without passing props--it does that through context.
Here, the `Heading` component determines its heading level by "asking" the closest `Section` for its level. Each `Section` tracks its own level by asking the parent `Section` and adding one to it. Every `Section` provides information to all components below it without passing props--it does that through Context.

<Sandpack>

Expand Down Expand Up @@ -795,15 +795,15 @@ export const LevelContext = createContext(0);

<LearnMore path="/learn/passing-data-deeply-with-context">

Read **[Passing Data Deeply with Context](/learn/passing-data-deeply-with-context)** to learn about using context as an alternative to passing props.
Read **[Passing Data Deeply with Context](/learn/passing-data-deeply-with-context)** to learn about using Context as an alternative to passing props.

</LearnMore>

## Scaling up with reducer and context {/*scaling-up-with-reducer-and-context*/}
## Scaling up with reducer and Context {/*scaling-up-with-reducer-and-context*/}

Reducers let you consolidate a component’s state update logic. Context lets you pass information deep down to other components. You can combine reducers and context together to manage state of a complex screen.
Reducers let you consolidate a component’s state update logic. Context lets you pass information deep down to other components. You can combine reducers and Context together to manage state of a complex screen.

With this approach, a parent component with complex state manages it with a reducer. Other components anywhere deep in the tree can read its state via context. They can also dispatch actions to update that state.
With this approach, a parent component with complex state manages it with a reducer. Other components anywhere deep in the tree can read its state via Context. They can also dispatch actions to update that state.

<Sandpack>

Expand Down
76 changes: 38 additions & 38 deletions src/content/learn/passing-data-deeply-with-context.md

Large diffs are not rendered by default.

48 changes: 24 additions & 24 deletions src/content/learn/scaling-up-with-reducer-and-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,21 +233,21 @@ In a small example like this, this works well, but if you have tens or hundreds

This is why, as an alternative to passing them through props, you might want to put both the `tasks` state and the `dispatch` function [into context.](/learn/passing-data-deeply-with-context) **This way, any component below `TaskApp` in the tree can read the tasks and dispatch actions without the repetitive "prop drilling".**

Here is how you can combine a reducer with context:
Here is how you can combine a reducer with Context:

1. **Create** the context.
2. **Put** state and dispatch into context.
3. **Use** context anywhere in the tree.
1. **Create** the Context.
2. **Put** state and dispatch into Context.
3. **Use** Context anywhere in the tree.

### Step 1: Create the context {/*step-1-create-the-context*/}
### Step 1: Create the Context {/*step-1-create-the-context*/}

The `useReducer` Hook returns the current `tasks` and the `dispatch` function that lets you update them:

```js
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
```

To pass them down the tree, you will [create](/learn/passing-data-deeply-with-context#step-2-use-the-context) two separate contexts:
To pass them down the tree, you will [create](/learn/passing-data-deeply-with-context#step-2-use-the-context) two separate Contexts:

- `TasksContext` provides the current list of tasks.
- `TasksDispatchContext` provides the function that lets components dispatch actions.
Expand Down Expand Up @@ -448,11 +448,11 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

Here, you're passing `null` as the default value to both contexts. The actual values will be provided by the `TaskApp` component.
Here, you're passing `null` as the default value to both Contexts. The actual values will be provided by the `TaskApp` component.

### Step 2: Put state and dispatch into context {/*step-2-put-state-and-dispatch-into-context*/}
### Step 2: Put state and dispatch into Context {/*step-2-put-state-and-dispatch-into-context*/}

Now you can import both contexts in your `TaskApp` component. Take the `tasks` and `dispatch` returned by `useReducer()` and [provide them](/learn/passing-data-deeply-with-context#step-3-provide-the-context) to the entire tree below:
Now you can import both Contexts in your `TaskApp` component. Take the `tasks` and `dispatch` returned by `useReducer()` and [provide them](/learn/passing-data-deeply-with-context#step-3-provide-the-context) to the entire tree below:

```js {4,7-8}
import { TasksContext, TasksDispatchContext } from './TasksContext.js';
Expand Down Expand Up @@ -671,7 +671,7 @@ ul, li { margin: 0; padding: 0; }

In the next step, you will remove prop passing.

### Step 3: Use context anywhere in the tree {/*step-3-use-context-anywhere-in-the-tree*/}
### Step 3: Use Context anywhere in the tree {/*step-3-use-context-anywhere-in-the-tree*/}

Now you don't need to pass the list of tasks or the event handlers down the tree:

Expand All @@ -693,7 +693,7 @@ export default function TaskList() {
// ...
```

To update the task list, any component can read the `dispatch` function from context and call it:
To update the task list, any component can read the `dispatch` function from Context and call it:

```js {3,9-13}
export default function AddTask() {
Expand All @@ -713,7 +713,7 @@ export default function AddTask() {
// ...
```

**The `TaskApp` component does not pass any event handlers down, and the `TaskList` does not pass any event handlers to the `Task` component either.** Each component reads the context that it needs:
**The `TaskApp` component does not pass any event handlers down, and the `TaskList` does not pass any event handlers to the `Task` component either.** Each component reads the Context that it needs:

<Sandpack>

Expand Down Expand Up @@ -897,11 +897,11 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

**The state still "lives" in the top-level `TaskApp` component, managed with `useReducer`.** But its `tasks` and `dispatch` are now available to every component below in the tree by importing and using these contexts.
**The state still "lives" in the top-level `TaskApp` component, managed with `useReducer`.** But its `tasks` and `dispatch` are now available to every component below in the tree by importing and using these Contexts.

## Moving all wiring into a single file {/*moving-all-wiring-into-a-single-file*/}

You don't have to do this, but you could further declutter the components by moving both reducer and context into a single file. Currently, `TasksContext.js` contains only two context declarations:
You don't have to do this, but you could further declutter the components by moving both reducer and Context into a single file. Currently, `TasksContext.js` contains only two Context declarations:

```js
import { createContext } from 'react';
Expand Down Expand Up @@ -1121,7 +1121,7 @@ ul, li { margin: 0; padding: 0; }

</Sandpack>

You can also export functions that _use_ the context from `TasksContext.js`:
You can also export functions that _use_ the Context from `TasksContext.js`:

```js
export function useTasks() {
Expand All @@ -1133,14 +1133,14 @@ export function useTasksDispatch() {
}
```

When a component needs to read context, it can do it through these functions:
When a component needs to read Context, it can do it through these functions:

```js
const tasks = useTasks();
const dispatch = useTasksDispatch();
```

This doesn't change the behavior in any way, but it lets you later split these contexts further or add some logic to these functions. **Now all of the context and reducer wiring is in `TasksContext.js`. This keeps the components clean and uncluttered, focused on what they display rather than where they get the data:**
This doesn't change the behavior in any way, but it lets you later split these Contexts further or add some logic to these functions. **Now all of the Context and reducer wiring is in `TasksContext.js`. This keeps the components clean and uncluttered, focused on what they display rather than where they get the data:**

<Sandpack>

Expand Down Expand Up @@ -1348,18 +1348,18 @@ Functions like `useTasks` and `useTasksDispatch` are called *[Custom Hooks.](/le

</Note>

As your app grows, you may have many context-reducer pairs like this. This is a powerful way to scale your app and [lift state up](/learn/sharing-state-between-components) without too much work whenever you want to access the data deep in the tree.
As your app grows, you may have many Context-reducer pairs like this. This is a powerful way to scale your app and [lift state up](/learn/sharing-state-between-components) without too much work whenever you want to access the data deep in the tree.

<Recap>

- You can combine reducer with context to let any component read and update state above it.
- You can combine reducer with Context to let any component read and update state above it.
- To provide state and the dispatch function to components below:
1. Create two contexts (for state and for dispatch functions).
2. Provide both contexts from the component that uses the reducer.
3. Use either context from components that need to read them.
1. Create two Contexts (for state and for dispatch functions).
2. Provide both Contexts from the component that uses the reducer.
3. Use either Context from components that need to read them.
- You can further declutter the components by moving all wiring into one file.
- You can export a component like `TasksProvider` that provides context.
- You can export a component like `TasksProvider` that provides Context.
- You can also export custom Hooks like `useTasks` and `useTasksDispatch` to read it.
- You can have many context-reducer pairs like this in your app.
- You can have many Context-reducer pairs like this in your app.

</Recap>
6 changes: 3 additions & 3 deletions src/content/learn/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export default function App() {

The [`useContext` Hook](/reference/react/useContext) is a technique for passing data down the component tree without having to pass props through components. It is used by creating a provider component and often by creating a Hook to consume the value in a child component.

The type of the value provided by the context is inferred from the value passed to the `createContext` call:
The type of the value provided by the Context is inferred from the value passed to the `createContext` call:

<Sandpack>

Expand Down Expand Up @@ -286,7 +286,7 @@ export default App = AppTSX;

This technique works when you have a default value which makes sense - but there are occasionally cases when you do not, and in those cases `null` can feel reasonable as a default value. However, to allow the type-system to understand your code, you need to explicitly set `ContextShape | null` on the `createContext`.

This causes the issue that you need to eliminate the `| null` in the type for context consumers. Our recommendation is to have the Hook do a runtime check for it's existence and throw an error when not present:
This causes the issue that you need to eliminate the `| null` in the type for Context consumers. Our recommendation is to have the Hook do a runtime check for its existence and throw an error when not present:

```js {5, 16-20}
import { createContext, useContext, useState, useMemo } from 'react';
Expand All @@ -296,7 +296,7 @@ type ComplexObject = {
kind: string
};

// The context is created with `| null` in the type, to accurately reflect the default value.
// The Context is created with `| null` in the type, to accurately reflect the default value.
const Context = createContext<ComplexObject | null>(null);

// The `| null` will be removed via the check in the Hook.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function Component() {
);
}

// ✅ Use context for global values
// ✅ Use Context for global values
function Component() {
const user = useContext(UserContext);
return <div>User: {user.id}</div>;
Expand Down
4 changes: 2 additions & 2 deletions src/content/reference/react-dom/createPortal.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { createPortal } from 'react-dom';

[See more examples below.](#usage)

A portal only changes the physical placement of the DOM node. In every other way, the JSX you render into a portal acts as a child node of the React component that renders it. For example, the child can access the context provided by the parent tree, and events bubble up from children to parents according to the React tree.
A portal only changes the physical placement of the DOM node. In every other way, the JSX you render into a portal acts as a child node of the React component that renders it. For example, the child can access the Context provided by the parent tree, and events bubble up from children to parents according to the React tree.

#### Parameters {/*parameters*/}

Expand Down Expand Up @@ -125,7 +125,7 @@ Notice how the second paragraph visually appears outside the parent `<div>` with
</body>
```

A portal only changes the physical placement of the DOM node. In every other way, the JSX you render into a portal acts as a child node of the React component that renders it. For example, the child can access the context provided by the parent tree, and events still bubble up from children to parents according to the React tree.
A portal only changes the physical placement of the DOM node. In every other way, the JSX you render into a portal acts as a child node of the React component that renders it. For example, the child can access the Context provided by the parent tree, and events still bubble up from children to parents according to the React tree.

---

Expand Down
16 changes: 8 additions & 8 deletions src/content/reference/react/Component.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ Only the `render` method is required, other methods are optional.

### `context` {/*context*/}

The [context](/learn/passing-data-deeply-with-context) of a class component is available as `this.context`. It is only available if you specify *which* context you want to receive using [`static contextType`](#static-contexttype).
The [Context](/learn/passing-data-deeply-with-context) of a class component is available as `this.context`. It is only available if you specify *which* Context you want to receive using [`static contextType`](#static-contexttype).

A class component can only read one context at a time.
A class component can only read one Context at a time.

```js {2,5}
class Button extends Component {
Expand Down Expand Up @@ -565,7 +565,7 @@ class Greeting extends Component {

React may call `render` at any moment, so you shouldn't assume that it runs at a particular time. Usually, the `render` method should return a piece of [JSX](/learn/writing-markup-with-jsx), but a few [other return types](#render-returns) (like strings) are supported. To calculate the returned JSX, the `render` method can read [`this.props`](#props), [`this.state`](#state), and [`this.context`](#context).

You should write the `render` method as a pure function, meaning that it should return the same result if props, state, and context are the same. It also shouldn't contain side effects (like setting up subscriptions) or interact with the browser APIs. Side effects should happen either in event handlers or methods like [`componentDidMount`.](#componentdidmount)
You should write the `render` method as a pure function, meaning that it should return the same result if props, state, and Context are the same. It also shouldn't contain side effects (like setting up subscriptions) or interact with the browser APIs. Side effects should happen either in event handlers or methods like [`componentDidMount`.](#componentdidmount)

#### Parameters {/*render-parameters*/}

Expand Down Expand Up @@ -714,7 +714,7 @@ React calls `shouldComponentUpdate` before rendering when new props or state are

- `nextProps`: The next props that the component is about to render with. Compare `nextProps` to [`this.props`](#props) to determine what changed.
- `nextState`: The next state that the component is about to render with. Compare `nextState` to [`this.state`](#props) to determine what changed.
- `nextContext`: The next context that the component is about to render with. Compare `nextContext` to [`this.context`](#context) to determine what changed. Only available if you specify [`static contextType`](#static-contexttype).
- `nextContext`: The next Context that the component is about to render with. Compare `nextContext` to [`this.context`](#context) to determine what changed. Only available if you specify [`static contextType`](#static-contexttype).

#### Returns {/*shouldcomponentupdate-returns*/}

Expand Down Expand Up @@ -789,7 +789,7 @@ If you define `UNSAFE_componentWillReceiveProps`, React will call it when the co
#### Parameters {/*unsafe_componentwillreceiveprops-parameters*/}

- `nextProps`: The next props that the component is about to receive from its parent component. Compare `nextProps` to [`this.props`](#props) to determine what changed.
- `nextContext`: The next context that the component is about to receive from the closest provider. Compare `nextContext` to [`this.context`](#context) to determine what changed. Only available if you specify [`static contextType`](#static-contexttype).
- `nextContext`: The next Context that the component is about to receive from the closest provider. Compare `nextContext` to [`this.context`](#context) to determine what changed. Only available if you specify [`static contextType`](#static-contexttype).

#### Returns {/*unsafe_componentwillreceiveprops-returns*/}

Expand Down Expand Up @@ -856,7 +856,7 @@ There is no direct equivalent to `UNSAFE_componentWillUpdate` in function compon

### `static contextType` {/*static-contexttype*/}

If you want to read [`this.context`](#context-instance-field) from your class component, you must specify which context it needs to read. The context you specify as the `static contextType` must be a value previously created by [`createContext`.](/reference/react/createContext)
If you want to read [`this.context`](#context-instance-field) from your class component, you must specify which Context it needs to read. The Context you specify as the `static contextType` must be a value previously created by [`createContext`.](/reference/react/createContext)

```js {2}
class Button extends Component {
Expand Down Expand Up @@ -1773,9 +1773,9 @@ If your component does not synchronize with any external systems, [you might not

---

### Migrating a component with context from a class to a function {/*migrating-a-component-with-context-from-a-class-to-a-function*/}
### Migrating a component with Context from a class to a function {/*migrating-a-component-with-context-from-a-class-to-a-function*/}

In this example, the `Panel` and `Button` class components read [context](/learn/passing-data-deeply-with-context) from [`this.context`:](#context)
In this example, the `Panel` and `Button` class components read [Context](/learn/passing-data-deeply-with-context) from [`this.context`:](#context)

<Sandpack>

Expand Down
Loading
Loading