React components communicate across hierarchies – Context

Github code address

Preface:

What if we need to pass data between two pages that are logically far apart? Pass it down through props layer by layer? Passing information through global variables?

  • If the middle of the props needs to be modified, is it necessary to modify each layer? Besides, the transfer work of layer by layer is also very heavy, which is quite troublesome.

  • If we use global variables to pass information, how do we ensure that the data is updated and its child components are refreshed? If you use forceUpdate to update components, this is obviously cumbersome, and global variables can cause global pollution.

B: well… The React component’s cross-hierarchy communication API context will be introduced

Context API
  1. Create a Context object

  2. Create the Provider and pass the value

  3. The child component consumes value

    1. contextType

      1. Can only be used with class components and can only subscribe to a single context source
    2. useContext

      1. Can only be used in function components or custom hooks
    3. consumer

      1. There are no restrictions on functions or class components

    // context.js

    import React from “react”;

    ​export const Context = React.createContext();

    ​export const UserContext = React.createContext();​

1. contextType
Contextcontext. js import React, {Component} from "React "; import { Context } from ".. /context"; Import ContextTypePage from "./ContextTypePage"; Export Default Class ContextPage extends Component {constructor(props) {super(props); this.state = { theme: { themeColor: "red" }, }; } render() { const { theme, user } = this.state; Return (<div> <h3>ContextPage</h3> < context. Provider value={theme}> // create context. Provider, Pass value <ContextTypePage /> // call child component to consume value </ context.provider > </div>); }} // contexttypePage.js import React, {Component} from "React "; Import {Context, /**UseContext**/} from ".. /context"; Export Default Class ContextPage extends Component {static contextType = Context; ContextType can only subscribe to a single context source, so if we get a UseContext here, // static contextType = UseContext; render() { const { themeColor } = this.context; return ( <div> <h3 className={themeColor}>ContextTypePage</h3> </div> ); }}Copy the code
2. useContext
Contextcontext. js import React, {Component} from "React "; import { Context, UserContext } from ".. /context"; Import ContextTypePage from "./ContextTypePage"; Import UseContextPage from "./UseContextPage"; Export Default Class ContextPage extends Component {constructor(props) {super(props); this.state = { theme: { themeColor: "red" }, user: { name: "xiaoming" }, }; } render() { const { theme, user } = this.state; return ( <div> <h3>ContextPage</h3> <Context.Provider value={theme}> <UserContext.Provider value={user}> // UserContext. The Provider, Pass value <ContextTypePage /> <UseContextPage /> // consume child component </ userContext.provider > </ context.provider > </div>); }} // usecontextPage.js import React from "React "; import { Context, UserContext } from ".. /context"; Export default function UseContextPage(props) {// Can only be used in function components or custom hooks // Multiple subscribed const theme = can be used React.useContext(Context); const user = React.useContext(UserContext); return ( <div> <h3 className={theme.themeColor}>UseContextPage</h3> <p>{user.name}</p> </div> ); }Copy the code
3. consumer
Contextcontext. js import React, {Component} from "React "; import { Context, UserContext } from ".. /context"; import ContextTypePage from "./ContextTypePage"; import UseContextPage from "./UseContextPage"; import ConsumerPage from "./ConsumerPage"; Export Default Class ContextPage extends Component {constructor(props) {super(props); this.state = { theme: { themeColor: "red" }, user: { name: "xiaoming" }, }; } render() { const { theme, user } = this.state; return ( <div> <h3>ContextPage</h3> <Context.Provider value={theme}> <UserContext.Provider value={user}> <ContextTypePage /> <UseContextPage /> <ConsumerPage /> // Child component consumption Value </ userContext.provider > </ context.provider > </div> ); Consumerpage. js import React, {Component} from "React "; import { Context, UserContext } from ".. /context"; export default class ConsumerPage extends Component { render() { return ( <div> <h3>ContextPage</h3> <Context.Consumer> // Create context. Consumer object {(theme, user) => { return ( <div className={theme.themeColor}> <UserContext.Consumer> {(user) => { return <div>{user.name}</div>; }} </UserContext.Consumer> </div> ); }} </Context.Consumer> </div> ); }}Copy the code