Communication between components in React (parent-child components, cross-level components, unrelated components)

Table of contents

Communication between parent and child components

Parent component passes data and methods to child component

Parent component obtains child component data and methods

Communication between cross-level components

Use props to implement cross-level component communication

Using context to implement cross-level component communication

Using state management to implement cross-level component communication

Communication between unrelated components

Use EventEmitter to implement communication between unrelated components

 Use state management to communicate between independent components

Supplement: Implement an EventEmitter yourself


Communication between parent and child components

Parent component passes data and methods to child component

The parent component can pass data and methods to the child component, and the child component obtains them through props.

Parent component:

import React from "react";
import Child from "./Child";
export default class Demo extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            value: 0
        }
        this.changeValue = this.changeValue.bind(this)
    }

    changeValue() {
        this.setState({
            value: this.state.value + 1
        }, () => {
            console.log('changeValue 方法执行了 value: ', this.state.value)
        })
    }

    render() {
        const value = this.state.value
        return (
            <div>
                <h1>父组件</h1>
                <p>value: {value}</p>
                <Child
                    // 向子组件传递数据
                    value={value}
                    // 向子组件传递方法
                    changeValue={this.changeValue}
                ></Child>
            </div>
        )
    }
}

Subassembly:

import React from "react";
export default class Child extends React.Component {

    constructor(props) {
        super(props)
    }
    dealClidk() {
        // 子组件触发父组件的方法执行
        this.props.changeValue()
    }
    render() {
        return (
            <div>
                <h1>子组件</h1>
                {/* 子组件通过props获取父组件传递的数据 */}
                <p>value:{this.props.value}</p>
                <button onClick={this.dealClidk.bind(this)}>点击</button>
            </div>
        )
    }
}

 

When the button in the child component is clicked, the property value in the parent component can be changed by triggering the method of the parent component. 

Parent component obtains child component data and methods

The parent component can obtain the data and methods of the child component through ref.

Parent component:

import React from "react";
import Child from "./Child";
export default class Demo extends React.Component {

    constructor(props) {
        super(props)
        this.ChildRef = React.createRef()
    }

    dealClidk() {
        if (this.ChildRef && this.ChildRef.current) {
            // 父组件触发子组件方法的执行
            this.ChildRef.current.changeValue()
        }
    }
    getData() {
        if (this.ChildRef && this.ChildRef.current) {
            // 父组件获取子组件中state的值
            const childData = this.ChildRef.current.state.data
            console.log('获取子组件的数据 childData: ', childData)
        }
    }

    render() {
        return (
            <div>
                <h1>父组件</h1>
                <button onClick={this.dealClidk.bind(this)}>点击</button>
                <button onClick={this.getData.bind(this)}>获取</button>
                <Child ref={this.ChildRef}></Child>
            </div>
        )
    }
}

Subassembly:

import React from "react";
export default class Child extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            data: 0
        }
        this.changeValue = this.changeValue.bind(this)
    }

    changeValue() {
        this.setState({
            data: this.state.data + 1
        }, () => {
            console.log('changeValue 方法执行了 data: ', this.state.data)
        })
    }

    render() {
        const data = this.state.data
        return (
            <div>
                <h1>子组件</h1>
                <p>value:{data}</p>
            </div>
        )
    }
}

Communication between cross-level components

Use props to implement cross-level component communication

There are also two ways to use props to achieve cross-level component communication.

Direct level-by-level transfer

Parent component: 

import React from "react";
import Child from "./Child";
export default class Demo extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            value: 0,
            value2: '张三'
        }
        this.changeValue = this.changeValue.bind(this)
    }

    changeValue() {
        this.setState({
            value: this.state.value + 1
        }, () => {
            console.log('changeValue 方法执行了 value: ', this.state.value)
        })
    }

    render() {
        const { value, value2 } = this.state
        return (
            <div>
                <h1>父组件</h1>
                <p>value: {value}</p>
                <p>value2: {value2}</p>
                <button onClick={this.changeValue}>点击</button>
                <Child
                    value={value}
                    value2={value2}
                ></Child>
            </div>
        )
    }
}

 Subassembly:

import React from "react";
import GrandSon from "./GrandSon";
export default class Child extends React.Component {

    render() {
        const { value, value2 } = this.props
        return (
            <div>
                <h1>子组件</h1>
                <GrandSon
                    // 子组件将数据继续向下传递
                    value={value}
                    value2={value2}
                ></GrandSon>
            </div>
        )
    }
}

Sun Tzu component

import React from "react";
export default class GrandSon extends React.Component {

    constructor(props) {
        super(props)
    }
    render() {
        const { value, value2 } = this.props
        return (
            <div>
                <h1>孙子组件</h1>
                <p>value: {value}</p>
                <p>value2: {value2}</p>
            </div>
        )
    }
}

This method is suitable for transferring less data and can be transferred one by one. If there is a lot of data to be transferred, using this method will easily cause code duplication. We can use {...this.props} to package and pass. No matter how much data is passed by the parent component, the child component will package all the data and pass it to the grandson component, and the grandson component can still use this.props to obtain it.

Let’s modify the delivery method of sub-components;

import React from "react";
import GrandSon from "./GrandSon";
export default class Child extends React.Component {

    render() {
        return (
            <div>
                <h1>子组件</h1>
                <GrandSon
                    // 子组件将数据继续向下传递
                    {...this.props}
                ></GrandSon>
            </div>
        )
    }
}

 

You can see that the same effect is achieved.

Using context to implement cross-level component communication

Using context to transfer data across levels requires the following steps:

1. Create a context instance through React.createContext()

import React from "react";
const DemoContext = React.createContext()

export default DemoContext;

2. Create a producer through provider. Provider has a value attribute that can be used to package the data that needs to be passed.

import React from "react";
import Child from "./Child";
import DemoContext from './DemoContext'
export default class Demo extends React.Component {

    constructor(props) {
        super(props)
        this.state = {
            value: 0,
            value2: '张三'
        }
        this.changeValue = this.changeValue.bind(this)
    }

    changeValue() {
        this.setState({
            value: this.state.value + 1
        }, () => {
            console.log('changeValue 方法执行了 value: ', this.state.value)
        })
    }

    render() {
        const { value, value2 } = this.state
        return (
            <div>
                <h1>父组件</h1>
                <p>value: {value}</p>
                <p>value2: {value2}</p>
                <button onClick={this.changeValue}>点击</button>
                <DemoContext.Provider value={
   
   {
                    value: value,
                    value2: value2
                }}>
                    <Child></Child>
                </DemoContext.Provider>
            </div>
        )
    }
}

3. Create a consumer through Consumer to receive the passed data

import React from "react";
import DemoContext from "./DemoContext";
export default class GrandSon extends React.Component {

    constructor(props) {
        super(props)
    }
    render() {
        return (
            <div>
                <h1>孙子组件</h1>
                <DemoContext.Consumer>
                    {/* Consumer中需要使用函数 */}
                    {
                        (value) => {
                            return (
                                <div>
                                    <p>value: {value.value}</p>
                                    <p>value2: {value.value2}</p>
                                </div>
                            )
                        }
                    }
                </DemoContext.Consumer>
            </div>
        )
    }
}

Intermediate components:

import React from "react";
import GrandSon from "./GrandSon";
export default class Child extends React.Component {

    render() {
        return (
            <div>
                <h1>子组件</h1>
                <GrandSon></GrandSon>
            </div>
        )
    }
}

Using state management to implement cross-level component communication

You can refer to the previous blog: React-redux global state management

Communication between unrelated components

Use EventEmitter to implement communication between unrelated components

Steps to use EventEmitter;

1. Install the events library

npm install events

2. Create an instance of EventEmitter

import React from "react";
import { EventEmitter } from "events";
// 创建EventEmitter实例
const DemoEvent = new EventEmitter()
export default DemoEvent;

3. Release events

Use emit("event name", parameters) to publish events

import React from "react";
import DemoEvent from './DemoEvent'
export default class GrandSon extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: 0
        }
        this.changeValue = this.changeValue.bind(this)
    }

    changeValue() {
        this.setState({
            value: this.state.value + 1
        }, () => {
            console.log('changeValue 方法执行了 value: ', this.state.value)
            // 发送一个事件
            DemoEvent.emit('sendData', this.state.value)
        })
    }

    render() {
        return (
            <div>
                <h1>孙子组件 GrandSon</h1>
                <p>{this.state.value}</p>
                <button onClick={this.changeValue}>点击</button>
            </div>
        )
    }
}

 4. Subscribe to events

To subscribe to events, you can use addListener("event name", callback function) or on("event name", callback function)

5. Cancel subscription

To unsubscribe, you can use removeListener("event name", callback function) or off("event name", callback function)

import React from "react";
import DemoEvent from './DemoEvent'
export default class GrandSon2 extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: 0
        }
        this.receiveData = this.receiveData.bind(this)
    }

    componentDidMount() {
        // 订阅事件
        DemoEvent.addListener('sendData', this.receiveData)
    }

    receiveData(data) {
        console.log('接收的数据 data: ', data)
        this.setState({
            value: data
        })
    }

    componentWillUnmount() {
        // 取消订阅
        DemoEvent.removeListener(this.receiveData)
    }

    render() {
        return (
            <div>
                <h1>孙子组件 GrandSon2</h1>
                <p>{this.state.value}</p>
            </div>
        )
    }
}

 

 Use state management to communicate between independent components

You can refer to the previous blog: React-redux global state management

Supplement: Implement an EventEmitter yourself

to be continued

Guess you like

Origin blog.csdn.net/Celester_best/article/details/126218290