React Context quick use

Posted by Loathor__Healer on Sun, 20 Feb 2022 13:19:49 +0100

1 use background

In order to transfer data across components, especially across multi-level components, using context can simplify the process and make it clearer. It should be noted that components that depend on context will be updated when the context changes (not controlled by shouldComponentUpdate)
It should be noted that the context comparison is shallow. If the context passed from the parent component to the child component is a new object, the child component will be updated.

Use of class 2 components

Note: the context must be stored separately, otherwise there may be reference problems, resulting in the inability to find the context, that is, the import loading order

  1. Declare context
// context.js
import React from 'react';
export const NameContext = React.createContext("xxx");
  1. Use Provider on parent component
// App.js
import React from "react";
import Page01 from "./routes/page01";
import { NameContext } from "./context/Context";
// export const NameContext = React.createContext("xxx");  Do not create a context here, but put it in a separate file
function App() {
  return (
    <NameContext.Provider value="xiaopi3">
      <div>
        <h1>This is a APP!</h1>
        <Page01 />
      </div>
    </NameContext.Provider>
  );
}

export default App;
  1. In the component to be used, declare contextType to use this context
// Page01.js
import React, { Component } from 'react'
import {NameContext} from '../../context/Context';

export default class Page01 extends Component {
  static contextType =  NameContext;
  render() {
    return (
      <div>
          <h1>It is currently a test page Page01!</h1>
          <div>{this.context}</div>
      </div>
    )
  }
}

Generally speaking, if you need to pass in the method to change the context, you need to pass its value and method as an object to the value of the provider (Note: value is a shallow comparison. If the reference is not changed, the page will not be updated, so the state of the class is used here, because a new state will be generated after calling setState)

// App.js
import React from "react";
import Page01 from "./routes/page01";
import { NameContext } from "./context/Context";

class App extends React.Component {
  state = {
    name: "xxx",
    changeName: (name) => this.setState({ name }),
  };
  render() {
    return (
      <NameContext.Provider value={this.state}>
        <div>
          <h1>This is a APP!</h1>
          <Page01 />
        </div>
      </NameContext.Provider>
    );
  }
}

export default App;

When using: this context. Changename ('pp ').

3 use of function components

Unlike class components, function components do not need to declare contextType, but need to use consumer in render:

// Class component
static contextType =  NameContext;
...
<div>{this.context}</div>
// Function component
import React from "react";
import { NameContext } from "../../../context/Context";

export default function Cp01() {
  return (
    <>
      I am N Generation subassembly
      <NameContext.Consumer>
        {(context) => (
          <>
            <div>{context.name}</div>
            <button onClick={()=>context.changeName("pp")}>changeName</button>
          </>
        )}
      </NameContext.Consumer>
    </>
  );
}

Note: context Consumer needs a function as a child element! Receive the current context value and return the react node.

4. Consume multiple context s

If a component needs to consume more than one context, it needs to be nested using consumer. At the same time, it also needs to be nested when passing value!

// provider nesting
<ThemeContext.Provider value={theme}>
  <UserContext.Provider value={signedInUser}>
    <Layout />
  </UserContext.Provider>
</ThemeContext.Provider>

// consumer nesting
<ThemeContext.Consumer>
  {theme => (
    <UserContext.Consumer>
      {user => (
        <ProfilePage user={user} theme={theme} />
      )}
    </UserContext.Consumer>
  )}
</ThemeContext.Consumer>

5 useContext

Note: like the non hook method, when the context is updated, the hook will trigger the component to re render, even if the parent component uses react Memo or shouldComponentUpdate.

The hook receives context: useContext(MyContext), which is equivalent to static contextType = MyContext or < mycontext in the class component Consumer>
Note: useContext(MyContext) only allows you to read the value of context and subscribe to the change of context. You still need to use < mycontext. Com in the upper component tree Provider > to provide context for lower level components.

Rewrite part of the code with hook:

// hook mode
import React,{useContext} from "react";
import { NameContext } from "../../../context/Context";

export default function Cp01() {
  const context = useContext(NameContext);
  return (
    <>
      Cp01
      <div>{context.name}</div>
      <button onClick={() => context.changeName("pp")}>changeName</button>
    </>
  );
}

Topics: Javascript Front-end React