React requires intercomponent communication in several cases:

  • The parent component communicates with the child component

  • The child component communicates with the parent component

  • Cross-level component communication

  • There is no communication between nested relational components

1. Parent components communicate with child components

It is most common for a parent component to communicate to a child component, with the parent component passing needed information to the child component via props.

Parent.jsx

import React, { Component } from 'react'; improt Child from './Child'; class Parent extends Component{ render(){ return( <div> <Child name = "son" /> </div> ); }}Copy the code

Child.jsx

import React from 'react'; import PropTypes from 'prop-types'; Export default function Child({name}){return <h1> Name {name}</h1>} child.propTypes = { name:PropTypes.String.isRequired, };Copy the code

2. Child components communicate with parent components

Using the callback function, using the custom event mechanism the following demo implements the function that can hide itself by clicking the Hide component button in a child component

List.jsx

import React, { Component } from 'react'; import PropTypes from 'prop-types'; class List extends Component { static propTypes = { hideComponent: PropTypes.func.isRequired, } render() {return (<div> < List < props. HideComponent}> </div>); } } export default List;Copy the code

APP.jsx

import React, { Component } from 'react'; import List3 from './components/List'; export default class App extends Component { constructor(... args) { super(... args); this.state = { isShowList: false, }; } showConponent = () => { this.setState({ isShowList: true, }); } hideConponent = () => { this.setState({ isShowList: false, }); Render () {return (<div> <button onClick={this.showconponent}> </button> {this.state.isshowList? <List hideConponent={this.hideConponent} />:null } </div> ); }}Copy the code

If you look at the implementation, you can see that it is implemented in the same way as a traditional callback function. And setState is usually paired with callback functions, which are traditionally functions that convert internal state.

3. Cross-level component communication

  • Layers of components pass props

For example, to communicate between component A and component B, component C needs to find the common parent of component A and component B. Component A communicates with component C first, and component C communicates with component B through component B. In this case, component C plays the role of middleware

  • Use the context

Context is a global variable, like a big container, that can be accessed anywhere. You can put information on the context that you want to communicate with, and then pull it from other components. React doesn’t recommend using a lot of context. We don’t know where the context is coming from; And context is a global variable, and global variables are where the application gets messy in the first place. ListItem is a child of List, and List is a child of app, listitem.jsx

import React, { Component } from 'react'; import PropTypes from 'prop-types'; Class ListItem extends Component {// A child Component declares itself to use context static contextTypes = {color: PropTypes.string, } static propTypes = { value: PropTypes.string, } render() { const { value } = this.props; return ( <li style={{ background: this.context.color }}> <span>{value}</span> </li> ); } }export default ListItem;Copy the code

List.jsx

import ListItem from './ListItem'; Class List extends Component {// The parent declares that it supports context static childContextTypes = {color: PropTypes.string, } static propTypes = { list: Proptypes.array,} // Provide a function to return the corresponding context object getChildContext() {return {color: 'red',}; } render() { const { list } = this.props; return ( <div> <ul> { list.map((entry, index) => <ListItem key={`list-${index}`} value={entry.text} />, ) } </ul> </div> ); } } export default List;Copy the code

App.jsx

import React, { Component } from 'react'; import List from './components/List'; Const list = [{text: the subject of 'a',}, {text: the subject of '2',},]; export default class App extends Component { render() { return ( <div> <List list={list} /> </div> ); }}Copy the code

4. Components without nested relationships

Use custom event mechanisms

In the componentDidMount event, subscribe to the event if the component is mounted; Unsubscribe from the componentWillUnmount event when the component is unmounted;

Take the common publish/subscribe model as an example, using the browser version of node.js Events module to implement

Use custom events

The component relationships in the following example: List1 and List2 do not have any nested relationships and App is their parent;

Implement such a function: click a button in List2, change the information display in List1

First you need to install the Events package in your project:

npm install events --save
Copy the code

Create an events.js file in a new util directory under SRC

import { EventEmitter } from 'events';
export default new EventEmitter();
Copy the code

list1.jsx

import React, { Component } from 'react'; import emitter from '.. /util/events'; class List extends Component { constructor(props) { super(props); this.state = { message: 'List1', }; } componentDidMount() {this.eventEmitter = Emitter. AddListener ('changeMessage', (message) => { this.setState({ message,}); }); } componentWillUnmount() { emitter.removeListener(this.eventEmitter); } render() { return ( <div>{this.state.message}</div> ); } }export default List;Copy the code

List2.jsx

import React, { Component } from 'react'; import emitter from '.. /util/events'; class List2 extends Component {handleClick = (message) => { emitter.emit('changeMessage', message); }; Render () {return (<div> <button onClick={this.handleclick.bind (this, 'List2')}> render() {return (<div> <button onClick={this.handleclick.bind (this, 'List2')}> }}Copy the code

APP.jsx

import React, { Component } from 'react'; import List1 from './components/List1'; import List2 from './components/List2'; export default class App extends Component { render() { return ( <div> <List1 /> <List2 /> </div> ); }}Copy the code

A custom event is a typical publish-subscribe pattern that communicates between components by adding listeners and triggering events to event objects

conclusion

  • Parent component communicates to child component: props

  • Child component communicates to parent: callback function/custom event

  • Cross-level component communication: Layers of components pass props/ Context

  • Communication between components without nested relationships: custom events