# React & Redux: Lesson6 Asynchronous Redux
###### tags: `Recat2`
# Introduction
{%youtube 0ioxfKg5yM8%}
# Connect & Provider
{%youtube 6Kfj_tRMJsI%}
## Getting the Store to Each Component
The first thing we want to do is improve how each component gets access to the store. If it's tough for a component to access the store, whether it's to get the state, listen to the state, or update the state, nothing else we do will matter. Right now we’re just passing the store down as a prop. It works fine enough in our small app, but what if we had a larger app with more layers to it? Passing the store down ten components deep wouldn't scale very well. One of the main points of having a store is to avoid passing props down through a bunch of components.
One reason React (talking about React for a moment, not Redux) is so popular is because it's very efficient. It's efficient in keeping state localized to a component, it's efficient in keeping UI confined to a component, and it's efficient in knowing when something has changed and re-rendering just that component. So the second thing we need need to figure out is how to re-render components only if the data they depend on (from the store) changes. Right now, we're solving this by calling getState at the root of our application and then passing the data down. Again, this won't scale well as our app grows.
If we can find a nice abstraction for getting the store to any component that needs it and only re-rendering components when the exact data they need change, we'll improve every aspect of our current codebase.
{%youtube 4jT0ws2UECE%}
{%youtube 6rVT0OVLt80%}
## Context
Before we add the `Context` API into our app, let's make sure we're on the same page as to how it all works.
Recall that in one of the previous screencasts, passing data from one component to another component was a bit cumbersome. We had to pass data from component to component:
```javascript
import React from 'react';
import { render } from 'react-dom';
function Parent ({ name }) {
return (
<div>
<h1>Parent</h1>
<Child name={name}/>
</div>
);
}
function Child ({ name }) {
return (
<div>
<h1>Child</h1>
<Grandchild name={name}/>
</div>
);
}
function Grandchild ({ name }) {
return (
<div>
<h1>Grandchild</h1>
<h3>Name: {name}</h3>
</div>
);
}
class App extends React.Component {
render() {
const name = 'Tyler';
return (
<Parent />
);
}
}
render(<App />, document.getElementById('root'));
```
The `App` component renders `Parent`, which renders `Child`, which renders `Grandchild`. However, what's important to notice here is that the `Grandchild` component wants to render `name` -- but the data for `name` lives inside the App component.
Because `Grandchild` is so deeply nested, we have to pass the `name` prop one-by-one from `App` through all the components until it reaches `Grandchild`. What's more: we must do this even if any of the components along the way (Parent and Child) aren't even concerned with the `name` data!
This process of "threading props" to send data to a child component can be tiresome, and perhaps even error-prone. Luckily, we can avoid it with React's Context API. To begin, we'll use React's `createContext()` function to return an object with a Provider as well as a Consumer.
```javascript
const Context = React.createContext();
```
Let's now check out how `Context.Provider` and `Context.Consumer` make these interactions between components possible!
## Context.Provider
The `Provider` component is used in the upper level of the component tree; that is, the component from which the data to be passed is held. In our case, this was the `App` component. We passed the `name` data as the value of `Provider`'s `value` prop:
```javascript
class App extends React.Component {
render() {
const name = 'Tyler';
return (
<Context.Provider value={name}>
<Parent />
</Context.Provider>
);
}
}
```
Note that the `Provider` component simply wraps around the entire component to be rendered!
## Context.Consumer
On the receiving end (i.e., a component "under" the `Provider` in the component hierarchy), we use the `Consumer` component. In our example, we passed `Consumer` a function as a child. This function accepts a value and returns some JSX:
```javascript
function Grandchild ({ name }) {
return (
<Context.Consumer>
{(name) => (
<div>
<h1>Grandchild</h1>
<h3>Name: {name}</h3>
</div>
)}
</Context.Consumer>
);
}
```
As a result, we were able to render the `Grandchild` component with the correct `name` data without ever having to pass that data down the entire component thread! That's a lot less code than the previous way we had to do it. So React's Context API provides a terse, approachable way to easily communicate information from one component to another.
Now, let's go ahead and utilize Context in our todos app.
[Context provides a way to pass data through the component tree without having to pass props down manually at every level.](https://reactjs.org/docs/context.html#reactcreatecontext)
{%youtube tlTJJ_v8ph0%}
In the previous video, I said both "Connected component" as well as "Container Component". These are different names that really mean the same thing - a component that is connected to the store. This is in contrast to a component that is just responsible for rendering UI content. We call these "Presentation Components". There are other names for a "Presentational Component", too.
The point of these names are to help explain what the purpose of the component is for:
- A connected component is connected to the Redux store and is responsible for getting data from the store.
- A presentational component should not access the store. It should receive any information it needs as props and then just render a UI.
Dan Abramov (the creator of Redux!) wrote a post about this very thing. Check it out if to get his take on these concepts: [Presentational and Container Components](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0)
# Folder Structure
# Lesson Summary
# 筆記
靠超好用的 Context.Consumer
如果有很多層component但是妳想要把父元件的東西一次傳到底層可以透過context.consumer來包住父元件並且把要傳送的內容放進去。之後任何底層的子元件component要使用,只需要透過Context.consumer來包住就好
## 步驟
1. 先產生context API
```javascript
const MyContext = React.createContext();
```
2. 決定資料的提供者
```javascript
class Provider extends React.Component{
render() {
return (
<MyContext.Provider value={this.props.store}>
{this.props.children}
</MyContext.Provider>
)
}
}
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('app')
)
```
3. Context的接收者
```javascript
class App extends React.Component {
...
render() {
return (
<Context.Consumer>
{(store) => {
...
}}
</Context.Comsumer>
)
}
}
```