Several modes of communication between components

Communication between parent and child components

Parent-to-child: The child component gets data passed by the parent component through props (this is the same as vue)

It's important to note that sometimes we may want to validate data passed to subcomponents, especially for large projects:

(1) If ts is used in a project, type validation can be performed directly.

(2) If not, type validation can also be done through the prop-types library.

import React, { Component } from 'react';
import PropTypes from 'prop-types';

function ChildCpn(props) {
  const { name, age, height } = props;

  return (
    <div>
      <h2>{name + age + height}</h2>
    </div>
  )
}

//Validation Writing in Class Components
class ChildCpn2 extends Component {
  static propTypes = {
      name: PropTypes.string.isRequired,
      age: PropTypes.number,
      height: PropTypes.number
  }
  static defaultProps = {
      name: "why",
      age: 30,
      height: 1.98
  }
}

//Verification Writing in Functional Components
ChildCpn.propTypes = {
  name: PropTypes.string.isRequired,
  age: PropTypes.number,
  height: PropTypes.number
}

ChildCpn.defaultProps = {
  name: "why",
  age: 30,
  height: 1.98
}

export default class App extends Component {
  render() {
    return (
      <div>
        <ChildCpn name="why" age={18} height={1.88} names={["abc", "cba"]} />
      </div>
    )
  }
}

Child heir: is also passed through props, except that the type passed is still a function in nature.

import React, { Component } from 'react';

class CounterButton extends Component {
  render() {
    const { onClick } = this.props;
    return <button onClick={onClick}>+1</button>
  }
}

export default class App extends Component {
  render() {
    return (
      <div>
        <CounterButton onClick={e => this.increment()} name="why" />
      </div>
    )
  }
}

Cross-component communication (context)

Sharing of data between non-parent and child components: react provides a way to share data between components: context.

(1) React.createContext (defaultValue): Create a context object that needs to be shared. Default Value is the default value that will be used if the component fails to find the corresponding provider during the layer-by-layer lookup process.

const UserContext = React.createContext(defaultValue);

(2)UserContext.Provider

//Wrap up the subcomponents you need to share) Now the subcomponents get what they want to share
<UserContext.Provider value={Incoming data that needs to be shared}>
    Subcomponents
</UserContext.Provider>

(3) Subcomponent name.contextType (typically used in class components because functional components do not have contexts and contextTypes): Subcomponent name.contextType = UserContext (At this point, the context in the render function has a value), so you can use this.context.data to get the shared value.It is important to note that in class components, contextType cannot be used to nest multiple layers, so functional components are recommended because consumer s of functional components can be used.

import React, { Component } from 'react';

// Step 1: Create a Context object and give it default values
const UserContext = React.createContext({
  nickname: "aaaa",
  level: -1
})

class ProfileHeader extends Component {
  render() {
    console.log(this.context);//There is value in the context at this point
    return (
      <div>
        <h2>nickname: {this.context.nickname}</h2>
        <h2>User Level: {this.context.level}</h2>
      </div>
    )
  }
}
//Step 3: Use shared values in subcomponents
ProfileHeader.contextType = UserContext;

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      nickname: "kobe",
      level: 99
    }
  }

  render() {
    return (
      <div>
        {/* Step 2: Share data by wrapping components that you want to share data with */}
        <UserContext.Provider value={this.state}>
          <ProfileHeader />
        </UserContext.Provider>
      </div>
    )
  }
}

(4) UserContext.Consumer: There is no contexts in function components and there is no contextType. It is important to note that createContext s can be nested in multiple layers, so it is generally recommended to use functional components and their consumers if there are multiple layers of nesting.

import React, { Component } from 'react';

// Step 1: Create Context Object &&Here are two shared objects to illustrate multilevel nesting
const UserContext = React.createContext({
  nickname: "aaaa",
  level: -1
})
const ThemeContext = React.createContext({
  color: "black"
})

function Profile() {
  // Step 3: How to share data in a multi-layer nested environment
  return (
    <UserContext.Consumer>
      {
        value => {
          return (
            <ThemeContext.Consumer>
              {
                theme => {
                  return (
                    <div>
                      <h2 style={{color: theme.color}}>nickname: {value.nickname}</h2>
                      <h2>User Level: {value.level}</h2>
                      <h2>colour: {theme.color}</h2>
                    </div>
                  )
                }
              }
            </ThemeContext.Consumer>
          )
        }
      }
    </UserContext.Consumer>
  )
}

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      nickname: "kobe",
      level: 99
    }
  }

  render() {
    return (
      <div>
        {/* Step 2: Share data by nesting multiple packages */}
        <UserContext.Provider value={this.state}>
          <ThemeContext.Provider value={{ color: "red" }}>
            <Profile />
          </ThemeContext.Provider>
        </UserContext.Provider>
      </div>
    )
  }
}

Event Bus

In vue2, we do this through EventBus.

In vue3, we do this with the mitt library.

In react, we can rely on an event library that uses a lot of events libraries to do this.

Some API s commonly used in the events library:

(1) Create EventEmitter objects: EventBus objects.

(2) Emit the event: eventBus.emit("Event name", parameter list).

(3) Listen for events: eventBus.addListener (Event Name, Listen Function).

(4) Remove the event: eventBus.removeListener("event name", listener function).

import React, { PureComponent } from 'react';
import { EventEmitter } from 'events';

// Step 1: Create an instance object
const eventBus = new EventEmitter();

class Home extends PureComponent {
  componentDidMount() {
    //Step 3: Listen for this event
    eventBus.addListener("sayHello", this.handleSayHelloListener);
  }
  componentWillUnmount() {
    //Step 4: Cancel listening on this event
    eventBus.removeListener("sayHello", this.handleSayHelloListener);
  }
  handleSayHelloListener(num, message) {
    console.log(num, message);
  }

  render() {
    return (
      <div>
        Home
      </div>
    )
  }
}

class Profile extends PureComponent {
  render() {
    return (
      <div>
        Profile
        <button onClick={e => this.emmitEvent()}>Clicked profile Button</button>
      </div>
    )
  }

  emmitEvent() {
    //Step 2: Send Events
    eventBus.emit("sayHello", 123, "Hello Home");
  }
}

export default class App extends PureComponent {
  render() {
    return (
      <div>
        <Home/>
        <Profile/>
      </div>
    )
  }
}

Keywords: React

Added by tmyonline on Tue, 14 Dec 2021 20:16:19 +0200