mirror of
https://github.com/microsoft/frontend-bootcamp.git
synced 2026-01-26 14:56:42 +08:00
Day 2 step 4 updates (#82)
This commit is contained in:
committed by
Kenneth Chau
parent
5b05aa45c9
commit
44682dac81
@@ -4,15 +4,13 @@
|
||||
|
||||
In this step, we describe some problems we encounter when creating a more complex application.
|
||||
|
||||
We will solve these problems with the React Context API. The Context API consists of Provider and Consumer components. Let's take a look at what is in this step:
|
||||
We will solve these problems with the [React Context API](https://reactjs.org/docs/context.html). The Context API consists of Provider and Consumer components. Let's take a look at what is in this step:
|
||||
|
||||
1. The problem of complex applications
|
||||
2. React Context API
|
||||
3. Consuming context from a Class Component
|
||||
4. Consuming context from a Functional Component
|
||||
|
||||
---
|
||||
|
||||
## The problem of complex applications
|
||||
|
||||
React represents a single component like this:
|
||||
@@ -25,9 +23,11 @@ In a real application, these functions are composed. It looks more like this:
|
||||
|
||||

|
||||
|
||||
1. Data needs to be passed down from component to component via props. Even when some components do not need to know about some data. This is a problem called **props drilling**
|
||||
Being able to compose components is helpful, but it introduces some complexity:
|
||||
|
||||
2. Shared data can be changed by various actors (user interaction, updates from server), and there is no coordination of these changes
|
||||
1. Data needs to be passed down from component to component via props--even if some of the intermediate components don't need to know about some of the data. This is a problem called **props drilling**.
|
||||
|
||||
2. Shared data can be changed by various actors (user interaction, updates from server), and there is no coordination of these changes. This makes propagating updates between components challenging.
|
||||
|
||||
Even in our simple application, we saw this problem. For example, `<TodoList>` has this props interface:
|
||||
|
||||
@@ -41,7 +41,7 @@ interface TodoListProps {
|
||||
}
|
||||
```
|
||||
|
||||
All of these props are not used, except to be passed down to a child Component, `TodoListItem`:
|
||||
None of these props are used in the `TodoList` itself; they're only passed down to child `TodoListItem` components:
|
||||
|
||||
```js
|
||||
<TodoListItem todos="{todos}" complete="{complete}" remove="{remove}" edit="{edit}" />
|
||||
@@ -49,20 +49,19 @@ All of these props are not used, except to be passed down to a child Component,
|
||||
|
||||
## React Context API
|
||||
|
||||
Let's solve these problems with the React Context API. Context is React's way to share data from components to their descendant children components without explicitly passing down through props at every level of the tree. In simpler terms, it solves the props drilling issue mentioned above!
|
||||
Let's solve these problems with the [React Context API](https://reactjs.org/docs/context.html). Context is React's way to share data from components with their child components without explicitly passing it down through props at every level of the tree. In simpler terms, it solves the props drilling issue mentioned above!
|
||||
|
||||
React context is created by calling `createContext()` with some initial data. Use the `<TodoContext.Provider>` component to wrap a part of the component tree that should be handed the context.
|
||||
|
||||
### Providing context with `<TodoContext.Provider>`
|
||||
|
||||
```js
|
||||
// To create a completed empty context
|
||||
// To create an empty context
|
||||
const TodoContext = React.createContext(undefined);
|
||||
|
||||
class TodoApp extends React.Component {
|
||||
render() {
|
||||
|
||||
// Pass in some state and function to the provider's value prop
|
||||
// Pass in some state and functions to the provider's value prop
|
||||
return (
|
||||
<TodoContext.Provider
|
||||
value={{
|
||||
@@ -84,7 +83,7 @@ class TodoApp extends React.Component {
|
||||
|
||||
### Consume context from a Class Component
|
||||
|
||||
Inside a class-based child component, such as the `<TodoHeader>` component, the value can be accessed from the component's `context` property like this:
|
||||
Inside a class-based child component, such as `<TodoHeader>`, the context created in the parent can be accessed via `this.context`. Note that for this to work, you must also set the component class's `contextType` property to the context type created above.
|
||||
|
||||
```js
|
||||
class TodoHeader extends React.Component {
|
||||
@@ -100,7 +99,7 @@ TodoHeader.contextType = TodoContext;
|
||||
|
||||
### Consume context from a Functional Component
|
||||
|
||||
If you're using the functional component syntax, you can access the context with the `useContext()` hook. Note that `useContext()` requires a recent release of React (16.8):
|
||||
If you're using the functional component syntax, you can access the context with the `useContext()` hook:
|
||||
|
||||
```js
|
||||
const TodoFooter = props => {
|
||||
@@ -113,4 +112,6 @@ const TodoFooter = props => {
|
||||
};
|
||||
```
|
||||
|
||||
> Note that `useContext()` requires a recent release of React (16.8+)
|
||||
|
||||
There is another legal syntax for accessing context with the `<TodoContext.Consumer>`, but we'll leave that out as an exercise for you!
|
||||
|
||||
@@ -14,14 +14,14 @@ If you don't already have the app running, start it by running `npm start` from
|
||||
|
||||
1. Open `exercise/src/components/TodoFooter.tsx`
|
||||
|
||||
2. Replace the two constants by using useContext(TodoContext)
|
||||
2. Use `useContext` to access the `TodoContext` and replace the two constants with values from the context
|
||||
|
||||
## TodoHeader, Context inside Class Component
|
||||
|
||||
1. Open `exercise/src/components/TodoHeader.tsx`
|
||||
|
||||
2. Replace the `onAdd` with a real implementation using the `this.context` object
|
||||
2. Replace `onAdd` with a real implementation using the `this.context` object
|
||||
|
||||
3. Replace the `onFilter` with a real implementation using the `this.context` object
|
||||
3. Replace `onFilter` with a real implementation using the `this.context` object
|
||||
|
||||
4. Be sure to set the `contextType` of the TodoHeader component
|
||||
|
||||
Reference in New Issue
Block a user