Introduction: In the latest React B-side project, Redux and other data management libraries were not used in the project, so the data transfer of many components and how to transfer nested components were involved. Therefore, we will sort out and record the new information by reviewing the past.

Common ways to set up communication:

  • Parent-child component communication
  • Child and parent components communicate
  • Sibling communication
  • Grandparent Communication (nested components)
  • , etc.

Code environment:

React: ^ 16.13.0 react – dom: ^ 16.8.2

Parent-child component communication:

Generally speaking, the parent component invokes the methods and properties of the child component by means of props, refs, etc.

Props: The child component accepts the value of the parent component for view updates

The class components:

import React, { Component } from 'react'

/ / child component
class Child extends Component {
  constructor(props) {
    super(props)
    this.state = {}
  }

  render() {
    const { mun } = this.props;
    return (
      <>Here is the child component:<p>{ mun }</p>
      </>)}}/ / the parent component
class Parent extends Component {
  constructor(props) {
    super(props)
    this.state = {
      mun:1
    }
  }

  handleParent = () = > {
    this.setState({
      mun: this.state.mun + 1})}render() {
    const { mun } = this.state
    return (
      <>
        <button onClick={this.handleParent}>I am the button of the parent component. You can click on me</button>
        <br />

        <Child mun={mun} />
      </>)}}export default Parent

Copy the code

Hooks components:

import React, { useState } from 'react'
const Child = (props) = > {

  const { mun } = props;
  return (
    <>Here is the child component:<p>{ mun }</p>
    </>)}const Parent = () = >{
  const [mun, setMun] = useState(0)

  const handleParent = () = > {
    setMun((value) = > {
      return value + 1})}return (
    <>
      <button onClick={handleParent}>I am the button of the parent component. You can click on me</button>
      <br />

      <Child mun={mun} />
    </>)}export default Parent
Copy the code

Refs: An object method used by the parent to manipulate the child by declaring ref to get the child’s object

The class components:

import React, { Component, createRef } from 'react'

/ / child component
class Child extends Component {
  constructor(props) {
    super(props)
    this.state = {
      mun:1}}// Subcomponents add and add
  accumulation = () = > {
    this.setState({
      mun: this.state.mun + 1})}render() {
    const { mun } = this.state
    return (
      <>Here is the child component:<p>{ mun }</p>
      </>)}}/ / the parent component
class Parent extends Component {
  constructor(props) {
    super(props)

    // control by ref
    this.createRef = createRef()
    this.state = {}
  }

  handleParent = () = > {
    this.createRef && this.createRef.current.accumulation()
  }

  render() {
    return (
      <>
        <button onClick={this.handleParent}>I am the button of the parent component. You can click on me</button>
        <br />

        <Child ref={this.createRef} />
      </>)}}export default Parent
Copy the code

Hooks components:

In hooks you need to get the value of the ref through the forwardRef forward and throw the child’s method to the parent through useImperativeHandle.

import React, { useRef, useState, useImperativeHandle, forwardRef } from 'react'

const Child = forwardRef((_, ref) = > {

  const [mun, setMun] = useState(0)

  // add method
  const accumulation = () = > {
    setMun((value) = > {
      return value + 1})}// Throw a method to the parent component
  useImperativeHandle(ref, () = > ({
    accumulation,
  }), [accumulation]);

  return (
    <>Here is the child component:<p>{ mun }</p>
    </>)})const Parent = () = >{
  const ChildRef = useRef(null);

  const handleParent = () = > {
    ChildRef.current && ChildRef.current.accumulation()
  }

  return (
    <>
      <button onClick={handleParent}>I am the button of the parent component. You can click on me</button>
      <br />

      <Child ref={ChildRef} />
    </>)}export default Parent

Copy the code

Parent component communication:

The child component retrieves methods or properties of the parent component through CallBack functions

The Class components:

import React, { Component, createRef } from 'react'

/ / child component
class Child extends Component {
  constructor(props) {
    super(props)
    this.state = {
      mun:0}}// Subcomponents add and add
  accumulation = () = > {
    const { handleParent } = this.props
    const { mun } = this.state

    this.setState({
      mun:this.state.mun + 1
    },() = > {
      handleParent(this.state.mun)
    })
  } 

  render() {
    const  { mun } = this.props
    return (
      <>Here is the child component: {/*<p>{ mun }</p>* /}<button onClick={this.accumulation}>I am the button of the child component that you can click on me</button>
      </>)}}/ / the parent component
class Parent extends Component {
  constructor(props) {
    super(props)

    // control by ref
    this.ChildRef = createRef()
    this.state = {
      getChildmun:0
    }
  }

  handleParent = (_mun) = > {
    this.setState({
      getChildmun:_mun
    })
  }

  render() {
    const { getChildmun } = this.state
    return (
      <>
        <h2>I'm the parent component</h2>
        <p>Values controlled by child components: {getChildmun}</p>
        <br />
        <Child handleParent={this.handleParent} />
      </>)}}export default Parent
Copy the code

Hooks components:

import React, { useState, useEffect } from 'react'

const Child = (props) = > {
  const { handleParent } = props;
  const [mun,setMun] = useState(0)

   // Subcomponents add and add
  const accumulation = () = > {
    setMun((value) = > {
      return value + 1
    })
  } 

  useEffect(() = > {
    if(mun ! = =0) {
      handleParent(mun)
    }
  }, [mun]);

  return (
    <>Here is the child component:<button onClick={accumulation}>I am the button of the child component that you can click on me</button>
    </>)}const Parent = () = >{
  const [getChildmun,setChildmun] = useState(0);

  return (
    <>
        <h2>I'm the parent component</h2>
        <p>Values controlled by child components: {getChildmun}</p>
        <br />
        <Child handleParent={(mun)= > setChildmun(mun)} />
    </>)}export default Parent

Copy the code

Sibling communication:

Sibling communication is usually two sibling components that are horizontal under one parent, using the parent as an intermediary

The Class components:

import React, { Component, createRef } from 'react'

// Subcomponent 1
class Child1 extends Component {
  constructor(props) {
    super(props)
    this.state = {
      mun:0}}render() {
    const { brother } = this.props

    return (
      <>
        <h2>I am Child1 component: {brother}</h2>
      </>)}}// Subcomponent 1
class Child2 extends Component {
  constructor(props) {
    super(props)
    this.state = {
      mun:0}}// Change its value and pass it through the parent component
  accumulation = () = > {
  const { brotherCallback } = this.props
    
   this.setState({
    mun:this.state.mun + 1
   }, () = > {
    brotherCallback(this.state.mun)
   })
  } 

  render() {
    const  { mun } = this.props
    return (
      <>
        <h2>I am Child2 component:</h2>
        <button onClick={ this.accumulation} >Click me to change the value of the [Child1] component</button>
      </>)}}/ / the parent component
class Parent extends Component {
  constructor(props) {
    super(props)

    // control by ref
    this.ChildRef = createRef()
    this.state = {
      brother:0}}// Use the mediation method
  brotherCallback = (mun) = > {
    this.setState({
      brother:mun
    })
  }

  render() {
    const { brother } = this.state 
    return (
      <>
        <h2>I'm the parent component</h2>
        <hr />
        <Child1 brother={brother} />
        <hr />
        <Child2 brotherCallback={this.brotherCallback}/>
      </>)}}export default Parent
Copy the code

Hooks components:

import React, { useState,useEffect } from 'react'

const Child1 = (props) = > {
  const { brother } = props;
  return (
    <>
       <h2>I am Child1 component: {brother}</h2>
    </>)}const Child2 = (props) = > {
  const [mun, setMun] = useState(0)
  const { brotherCallback } = props

  // Change its value and pass it through the parent component
  const accumulation = () = > {
    setMun((value) = > {
      return value + 1
    })
  } 

  useEffect(() = > {
   if(mun ! = =0 ) {
    brotherCallback(mun)
   }
  }, [mun])

  return (
    <>
      <h2>I am Child2 component:</h2>
      <button onClick={accumulation} >Click me to change the value of the [Child1] component</button>
    </>)}const Parent = () = > {
  const [brother,setBrother] = useState(0);
  return (
    <>
       <h2>I'm the parent component</h2>
        <hr />
        <Child1 brother={brother} />
        <hr />
        <Child2 brotherCallback={(mun)= > setBrother(mun)}/>
    </>)}export default Parent
Copy the code

Nested components:

Nested components can also be passed by parent components, but if the hierarchy is too deep, it is difficult to maintain, so Context is recommended to maintain the state of the data source

See the Context documentation for details.

The Class components:

import React, { Component, createRef } from 'react'

// Can put it in a separate js file maintenance
const ThemeContext = React.createContext();

// Grandchild component
class Grandson extends Component{
  constructor(props) {
    super(props)
    this.state = {}
  }

  static contextType = ThemeContext;
  
  shouting = () = > {
    const { grandsonCallback } = this.context
    grandsonCallback({
      massge:"I'm tired. Ruin it."})}render() {
    const { parentObj } = this.context
    return (
      <>
       <h2>I am sun Tzu component</h2>
       <p>Received values: {parentobj.name} age {parentobj.age} age</p>
       <button onClick={this.shouting}>Every song words</button>
      </>)}}// Son component
class Child extends Component {
  constructor(props) {
    super(props)
    this.state = {}
  }

  render() {
    return (
      <>
       <h2>I am the son component</h2>
       <hr />
       <Grandson />
      </>)}}/ / the parent component
class Parent extends Component {
  constructor(props) {
    super(props)

    this.state = {
      parentObj: {name:"I'm your grandfather.".age:88
      },
      // Accept data from the grandchild component
      grandson:{}
    }
  }

  grandsonCallback = (data) = > {
    this.setState({
      grandson:data
    })
  }
  render() {
    const { parentObj, grandson } = this.state;
    return (
      <>
        <h2>I'm the parent component</h2>
        <p>{( grandson && grandson.massge ) ? grandson.massge : '' }</p>
        <hr />
        <ThemeContext.Provider value={ { parentObj.grandsonCallback: this.grandsonCallback } }>
          <Child />
        </ThemeContext.Provider>
      </>)}}export default Parent
Copy the code

Hooks components:

import React, { useState, useContext } from 'react'

// Can put it in a separate js file maintenance
const ThemeContext = React.createContext();

const Grandson = () = > {
  const context = useContext(ThemeContext)
  const { parentObj, grandsonCallback } = context;

  const shouting = () = > {
    grandsonCallback({
      massge:"I'm tired. Ruin it."})}return (
    <>
     <h2>I am sun Tzu component</h2>
     <p>Received values: {parentobj.name} age {parentobj.age} age</p>
     <button onClick={shouting}>Every song words</button>
    </>)}const Child = () = > {
  return (
    <>
      <h2>I am the son component</h2>
      <hr />
      <Grandson />
    </>)}const Parent = () = >{
  const [grandson, setGrandson] = useState({});
  const [parentObj, setParentObj] = useState(
  {
    name:"I'm your grandfather.".age:88
  });

  const grandsonCallback = (data) = > {
    setGrandson(data)
  }

  return (
    <>
      <h2>I'm the parent component</h2>
      <p>{( grandson && grandson.massge ) ? grandson.massge : '' }</p>
      <hr />
      <ThemeContext.Provider value={ { parentObj.grandsonCallback } }>
        <Child />
      </ThemeContext.Provider>
    </>)}export default Parent
Copy the code

The last

In fact, the above method is sufficient for common component communication, but it is still recommended to use state storage objects such as Redux for unified management in complex and large projects. If Redux is not flexible, it is also recommended to use DVA for management, just like its characteristics: quick to use, easy to learn and use.