Component communication across hierarchies – Context
A concept.
Context provides a way to pass data across the component tree without manually adding props for each layer of components.
2. The API
- React.createContext
const MyContext = React.createContext(defaultValue);
Copy the code
- Context.Provider
< myContext. Provider value={/* some value */}>Copy the code
- Class.contexttype (can only be used on Class components, can only subscribe to a single contextType)
class MyClass extends React.Component {
static contextType = MyContext;
render() {
letvalue = this.context; /* Render work based on this value */}}Copy the code
- Context.Consumer
< mycontext.consumer > {value => /* Render based on the context value */} </ mycontext.consumer >Copy the code
- UseContext (hook method, can only be used in function components or custom hooks)
Iii. Application in actual projects
- Create a new file – SRC/contenxt.js – that defines createContext, Provider, and Consumer
import React from "react";
export const ThemeContext = React.createContext({themeColor: "pink"});
export const ThemeProvider = ThemeContext.Provider;
export const ThemeConsumer = ThemeContext.Consumer;
export const UserContext = React.createContext();
export const UserProvider = UserContext.Provider;
export const UserConsumer = UserContext.Consumer;
Copy the code
- The page introduction – SRC/pages/ContextPage js, and provide the value
import React, {Component} from "react";
import {ThemeProvider, UserProvider, UserContext} from ".. /Context";
import ConsumerPage from "./ConsumerPage";
import UseContextPage from "./UseContextPage";
export default class ContextPage extends Component {
constructor(props) {
super(props);
this.state = {
theme: {
themeColor: "red"
},
user: {name: "Zeng Xiaobai"}}; }render() {
const {theme, user} = this.state;
return( <div> <h3>ContextPage</h3> <ThemeProvider value={theme}> <UserProvider value={user}> <ConsumerPage /> <UseContextPage /> </UserProvider> </ThemeProvider> </div> ); }}Copy the code
- In the page to receive – SRC/pages/ConsumerPage js, receives the value
import React, {Component} from "react";
import {ThemeConsumer, UserConsumer} from ".. /Context";
export default class ConsumerPage extends Component {
render() {
return (
<div>
<h3>ConsumerPage</h3>
<ThemeConsumer>
{themeContext => (
<div className={themeContext.themeColor}>
omg
<UserConsumer>
{userContext => <Child {...userContext} />}
</UserConsumer>
</div>
)}
</ThemeConsumer>
</div>
);
}
}
function Child(props) {
return <div>{props.name}</div>;
}
Copy the code
- Used in the function – SRC/pages/UseContextPage js, use useContext
import React, {useContext} from "react";
import {ThemeContext, UserContext} from ".. /Context";
export default function UseContextPage(props) {
const {themeColor} = useContext(ThemeContext);
const {name} = useContext(UserContext);
return (
<div className="border">
<h3 className={themeColor}>UseContextPage</h3>
<p>{name}</p>
</div>
);
}
Copy the code
Pay attention to
For example, every time the Provider rerenders, the following code will rerender all of the following consumers components. Because the value property is always assigned to the new object:
class App extends React.Component {
render() {
return (
<Provider value={{something: 'something'}}> <Toolbar /> </Provider> ); }}Copy the code
To prevent this, promote the value state to the parent node’s state
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
value: {something: 'something'}}; }render() {
return( <Provider value={this.state.value}> <Toolbar /> </Provider> ); }}Copy the code
conclusion
- What we’re going to learn about react-redux is that we’re going to use Context to provide a global store,
- The react-router routing component uses Context to manage routing state and so on.