When we use React, communication (data passing) between components is unavoidable.

Note that the flow of data in React is one-way

Data transfer between components can be divided into the following categories:

  • The parent component passes data to the child component

  • The child component passes data to the parent

  • Passing data between components across levels (for example, a parent passing data to a child)

  • Data is passed between non-nested components

Let’s use two methods (props and Context) and write code to implement each of the four communication methods

Overall communication diagram:

Operation effect:

usepropscommunication

Directly on the code:

import React, { Component } from 'react'; class App extends Component { state = { color: 'red' } changeColor = color => { this.setState({ color: color }) } render() { return ( <div style={{ border: `8px solid ${this.state.color}`, padding: "5px", margin: '5px' }}> <h1>Wrapper</h1> <Header color={this.state.color}></Header> <Main changeColor={this.changeColor.bind(this)} color={this.state.color}></Main> </div> ) } } class Header extends Component { render() { return ( <div style={{ border:  `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}> <h1>Header</h1> <Title color={this.props.color}></Title> </div> ) } } class Title extends Component { render()  { return ( <div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}> <h1>Title</h1> </div> ) } } class Main extends Component { render() { return ( <div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}> <h1>Main</h1> <Content changeColor={this.props.changeColor} color={this.props.color}></Content> </div> ) } } class Content extends Component { render() { return ( <div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px'}}> <h1>Content</h1> <button onClick={()=>this.props. ChangeColor ("blue")} OnClick ={()=>this.props. ChangeColor ("green")}> </button> </div>)}} export default App;Copy the code

Illustration:

usecontextcommunication

The code above must have noticed that if the child component needs to use the state of the parent component, the pass code needs to be written in the component level by level

And there are only two levels nested inside, and there are fewer components. What if there are more components and more states? React uses the react API Context to solve the problem. Use the react API Context

Of course, this is not the optimal solution. For large projects, it is best to use Redux to manage our state. For small projects, there is no need to use Redux because React provides state management itself

The code:

import React, { Component } from 'react'; // Create a context using the API provided in react let ColorContext = reace.createcontext (); // The Context object provides two apis, The Provider provides data // and the Consumer, // Static contextType = ColorContext; // contextType = ColorContext; Class App extends Component {state = {color: contextType = contextType; 'red'} changeColor = color => {this.setState({color: color})} render() {// Get data into the context let contextValue = {color: this.state.color, changeColor: This.changecolor} return (// wrap all the components we wrote with the context component we created, and use the value binding data < colorContext.provider value={contextValue}> <div style={{ border: `8px solid ${this.state.color}`, padding: "5px", margin: '5 px'}} > < h1 > Wrapper < / h1 > {/ * here we do not need to bind the * /} < Header > < Header > < Main > < / Main > < / div > < / ColorContext Provider >)}} Class Header extends Component {class Header extends Component {class Header extends Component {class Header extends Component {class Header extends Component {class Header extends Component { Static contextType = ColorContext; static contextType = ColorContext; <div style={{border: '8px solid ${this.context.color}', padding: "5px", margin: '5px' }}> <h1>Header</h1> <Title></Title> </div> ) } } class Title extends Component { static contextType = ColorContext; render() { return ( <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}> <h1>Title</h1> </div> ) } } class Main extends Component { static contextType = ColorContext; render() { return ( <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}> <h1>Main</h1> <Content></Content> </div> ) } } class Content extends Component { static contextType = ColorContext; render() { return ( <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px'}}> <h1>Content</h1> <button onClick={() => this.context.changecolor ("blue")}> This.context.changecolor ("green")}> </button> </div>)}} export default App;Copy the code

Illustration:

Use context in a class component, but what about a function component instead of a class component? How do you use context?

Here we replace the class component of Main with a function component:

import React, { Component } from 'react'; let ColorContext = React.createContext(); class App extends Component { state = { color: 'red' } changeColor = color => { this.setState({ color: color }) } render() { let contextValue = { color: this.state.color, changeColor: this.changeColor } return ( <ColorContext.Provider value={contextValue}> <div style={{ border: `8px solid ${this.state.color}`, padding: "5px", margin: '5px' }}> <h1>Wrapper</h1> <Header></Header> <Main></Main> </div> </ColorContext.Provider> ) } } class Header extends Component { static contextType = ColorContext; render() { return ( <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}> <h1>Header</h1> <Title></Title> </div> ) } } class Title extends Component { static contextType = ColorContext; render() { return ( <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}> <h1>Title</h1> </div> ) } } // class Main extends Component { // static contextType = ColorContext; // render() { // return ( // <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}> // <h1>Main</h1> // <Content></Content> // </div> // ) // } // } function Main() { return ( Consumer> {value => (<div style={{border: `8px solid ${value.color}`, padding: "5px", margin: '5px' }}> <h1>Main</h1> <Content></Content> </div> ) } </ColorContext.Consumer> ) } class Content extends Component { static contextType = ColorContext; render() { return ( <div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px'}}> <h1>Content</h1> <button onClick={() => this.context.changecolor ("blue")}> This.context.changecolor ("green")}> </button> </div>)}} export default App;Copy the code

In fact, all of these communication methods can be used when components communicate with each other. The difference is the complexity of using the corresponding communication method and personal preference, choosing the most appropriate one.

Of course, it’s still too difficult to manage communication between components yourself, so there are a number of state management tools, such as Redux, MOBx, etc., that make it easier to track and manage communication between components.


TAT