preface

Front-end projects are made up of individual pages. For Vue, a page is made up of multiple components, and the page itself is also a routing component. The same is true for React. Vue provides a series of technical support to complete the development of a component. You can start with the technical support in React to learn about React, such as how to develop the UI of components in React, how to use components in React, and how to define component data in React.

1. Scaffolding

UmiJS scaffolding is similar to VueCli, at least in terms of routing configuration. Install React with UmiJS as follows:

  • mkdir myapp && cd myapp
  • NPM create@umijs /umi-app Creates the React project
  • NPM install Installs dependencies
  • Run the NPM run start command to start the project

Myapp directory engineering structure is as follows:

├ ─ ─ package. Json ├ ─ ─ the umirc. Ts ├ ─ ─ the env ├ ─ ─ dist ├ ─ ─ the mock ├ ─ ─ public └ ─ ─ the SRC ├ ─ ─ the umi ├ ─ ─ layouts/index. The TSX ├ ─ ─ pages ├── lessons.lessons.exercises ─ lessons.exercisesCopy the code

. The contents of the umirc.ts file are as follows:

import { defineConfig } from 'umi';

export default defineConfig({
  nodeModulesTransform: {
    type: 'none',},routes: [{path: '/'.component: '@/pages/index'},].fastRefresh: {},});Copy the code

The routing configuration is similar to Vue Router

Develop components in React

2.1 Component writing

ES6 class

import React from 'react';
export default class HelloWorld extends React.Component {
    constructor(props){
        super(props);
    }
    
    render(){
        return (
            <div>hello world</div>)}}Copy the code

Function form, called function component:

export default function HelloWorld(){
    return (
        <div>hello world</div>)}Copy the code

Note that the first letter of the function name is capitalized

2.2 Binding Class and Style

React uses className to bind class and style to bind style. Where style takes an object and is passed in as {}, and the object’s attribute names can only be named in camel case

Class component written:


consturctor(props){
    super(props);
    this.state = {
        styleData: {color: 'red' , fontSize: '16px'},isHead: true , 
        className: 'title'}}render(){
    <div
        className={` ${this.state.className} ${this.state.isHead ? 'head':"'} `}style={this.state.styleData} />
        hello world
    </div>
}
Copy the code

Functional component

export default function HelloWorld(){
    const [styelData] = useState({color: 'red' , fontSize: '16px'});
    const [isHead] = useState(true );
    const [className] = useState('title');
    
    return (
        <div 
            className={` ${className} ${isHead ? 'head':"'} `}style={styleData} />
            hello world;
        </div>
    )
}
Copy the code

React uses {} to assign variables to attributes, and className only accepts strings, not arrays or objects. You can use ES6 template strings to concatenate variables to generate strings

React uses components

As with Vue, components that use import in React must be named with uppercase letters because React treats components that start with lowercase letters as native DOM tags

How do you define component data in React

In React, the internal data is called state and the parameter data is called props

4.1 Defining internal data states

this.state = {
    styleData: {},className: 'title' 
}
/ / or
const [styleData] = useState({})
const [className] = useState()
Copy the code

It is recommended to develop the React component in a functional form. You can use React Hook to avoid learning how to refer to this in a class.

4.2 Parameter Data Props

  • Class component writing
class HelloWorld extends React.Component{
    constructor(props){
        super(props);
    }
}
HelloWorld.defaultProps = {
    title: 'hello world'
}
Copy the code

The constructor function in the class component accepts props as the set of parameters passed in and calls super(props) to pass the props to the react.componentconstructor so that the class component can accept the collective props of the parameter data. This.props. Title is used to read the title parameter, and defaultProps is used to define the default value of the title parameter.

  • Function component writing
export default function HelloWorld(props){
    const {title = 'hello world'} = props ;
}
Copy the code

The function component receives a props as a set of parameter data passed to the component. It uses ES6’s destruct assignment function to get the parameter data of the component, and can set default values for the parameter data. Note: Vue uses {{}} to use data in its Template template, while React uses {} to use data in its React template

React implements component transfer of data

  • Passing dynamic data
<HelloWorld 
    style={styleData}
    isHead={isHead}
    className={className}
Copy the code
  • Passing string data
<HelloWorld title="title" />
Copy the code
  • Pass numeric type data
<HelloWorld num={1} / >Copy the code
  • Pass Boolean data
<HelloWorld isHead={false} / >Copy the code
  • Pass array type data
<HelloWorld className={['title' , 'head']} / >Copy the code
  • Pass static data of the object type
<HelloWorld styleData={{color: 'red' , fontSize: '16px'}} / >Copy the code

React listens for DOM events

  • Class component writing
import React from 'react'
export default class Hello extends React.Component{
    constructor(props){
        super(props);
        this.click = this.click.bind(this);
    }
    click(){}render(){
        return (
            <div onClick={this.click} /></div>
        )
    }
}
Copy the code
  • Functional component writing
export default function Hello(){
    const click = () = >{}return (
        <div onClick={this.click} /></div>
    )
}
Copy the code

React uses onClick to listen for click events. OnClick is a synthetic event. In Vue, @ represents a listening event, but is a native event. React onClick is a synthetic event that represents an event overwritten by React.

** The component listens for events similar to the DOM events above **

React changes component data

The Props data in React and Vue data cannot be modified, so only the state data can be modified. The data that you want to modify is only modified in the parent component and then passed to the child component via component communication.

  • Class component writing
class Hello extends React.Component{
    constructor(props){
        super(props)
        this.state = {
            count: 0
        }
        this.click = this.click.bind(this);
    }
    
    click(){
        this.setState({
            count: 1}}})Copy the code

In this.setState, we can pass a function or an object. It is recommended that we pass a function (state, props) => {}. The function can accept internal data state and parameter data props as arguments. In addition, state and props are read-only and cannot be modified. Each time this. SetState is called, the state and props are read as the latest. Finally, the function returns an object containing the state to be modified.

In React, internal data is called state. When using useState(param) to define a state, you can use the param parameter to set the default value of state, which returns an array with state as the first value. The second value of the array is the function that changes state, which can be called to change state

In addition, the data defined with useState is reactive. If the page has usage data, the page will be re-rendered after the data changes.

8. Component communication

The parent passes data to the child component, as Vue does, via props

If you want to realize the child component to modify the parent component’s data method, you can only pass the method from the parent component to the child component, and then the child component calls the parent component’s method for modification and processing (actually similar to emit in Vue).

  • Class component writing
/ / the parent component
class Index extends React.Component{
    constructor(props){
        super(props);
        this.click = this.clicl.bind(this);
        this.state = {
            title: 'titleInfo'}}click(data){
        this.setState(state= > {
            return {
                title: data
            }
        })
    }
    
    render(){
        return (
            <Hello title={this.state.title} changeTitle={this.click} />)}}Copy the code
/ / child component
class Hello extends React.Component{
    constructor(props){
        super(props);
        this.changeClick = this.changeClick.bind(this);
    }
    changeClick(){
        this.props.changeTitle('data');
    }
    render(){
        return {
            <div onClick={this.changeClick}></div>}}}Copy the code
  • Functional component writing
/ / the parent component
function Index(){
    const [title , setTitle] = useState('title');
    const click = (data) = > {
        setTitle(data);
    }
    return (
        <Hellow title={title} changeTitle={click} />)}Copy the code
/ / child component
function Hello(props){
    const { title = 'title' , changeTitle } = props;
    const handleChangeClick = () = >{
        changeTitle('data');
    }
    
    return (
        <div onClick={handleChangeClick}>{title}</div>)}Copy the code

React monitors data changes

  • Class component writing

ComponentDidUpdate is used to implement the life cycle method componentDidUpdate in the class component. This method will not be executed when rendering for the first time, but will be triggered when props and state change later. Its accepted parameters are: PrevProps and prevState represent props and state before the change, respectively.

  • I’ll write it as a function

In a functional component, you can use the useEffect Hook to listen for data changes, but you cannot get the data before the change as in the class component writing. Therefore, you need to customize the Hook function (useWatch). As follows:

When the useWatch is triggered for the first time, the old data can be stored in a container. When the useWatch is triggered next time, the old data before the change can be obtained by reading the value in the container. Containers can be created using the useRef Hook.

UseRef returns a mutable ref object whose.current property is initialized as the passed parameter (initialValue). The ref object returned remains constant throughout the life of the component.

import {useEffect , useRef} from 'react'
export function useWatch(value , callback){
    const oldValue = useRef();
    useEffect( () = > {
        callback( value , oldValue.current ) ;
        oldValue.current = value;
    } , [value] )
}
Copy the code

The useEffect function is called once after the component is first rendered, causing the callback function to be executed once. In addition, Vue can use the immediate configuration to control the execution of the callback function immediately after the component is first rendered. By default, callback is not executed after the first rendering of the component. Meanwhile, Vue’s watch also returns an unwatch function, which can be called to stop listening to the data. So the complete code is as follows:

import {useEffect , useRef} from 'react'
export function useWatch(value , callback , config = {immediate: false}){
    const oldValue = useRef();
    const isInit = useRef(false);
    const isWatch = useRef(ture);
    useEffect( () = > {
        if(isWatch.current){
            if(! isInit.current){ isInit.current =true ; 
                if(config.immediate){ callback(value , oldValue.current); }}else{
                callback(value , oldValue.current)
            }
            oldValue.current = value;
        }
    } , [value] )
    const unwatch = () = >{
        isWatch.current = false ;
    }
    return unwatch ; 
}
Copy the code

React: The parent component calls the child component’s methods

The implementation method is basically the same as that in Vue3

  • Class component methods: Use the react.createref () method
/ / the parent component
class Index extends React.Component{
    constructor(props){
        super(props);
        this.myCom = React.createRef();
        this.click = this.click.bind(this);
    }
    click(){
        this.myCom.current.handle();
    }
    render() {
        return (
            <Hello ref={this.myCom} />
            <div onClick={this.click}> Hello World </div>)}}/ / child component
class Hello extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            title: 'hello'}}handle(){
        this.setState(state= > {
            title: 'myCom'})}render() {
        return (
            <div> {title} </div>)}}Copy the code
  • Functional component writing

UseRef () cannot be used on function components. UseImperativeHandle defines the instance value to be exposed to the parent component and passes it to the forwardRef to export

/ / the parent component
function Index(){
    const myCom = useRef();
    changeTitle = () = > {
        myCom.current.handleChangeTitle();
    }
    return (
        <Hello ref={myCom} />
        <button onClick={changeTitle}>Change the title</button>)}/ / child component
function Hello(props , ref){
    const [title , setTitle] = useState('hello world');
    useImperativeHandle(ref , () = > ({
        handleChangeTitle: () = >{
            setTitle('two')}}))return (
        <div></div>)}Copy the code

11. Component slots

  • Ordinary slot

This can be obtained directly from this.props. Children; The difference between a classified component and a functional component is the difference between obtaining the content of props

  • A named slot

You can pass a function to the child component via props, and if the function returns the React element, which is written in JSX syntax, you implement the named slot function indirectly.

  • Class component writing
/ / the parent component
import React from 'react';
import HelloWorld from './HelloWorld.js';
class Index extends React.Component{
  constructor(props) {
    super(props);
  }
  info(){
    return(
      <span>hello World</span>)}render() {
    return (
      <HelloWorld element={this.info}></HelloWorld>)}}export default Index;
/ / child component
import React from 'react';
class HelloWorld extends React.Component{
  constructor(props){
    super(props)
    this.elementSlot = "";
    if (this.props.element) {
      this.elementSlot = this.props.element(); }}render(){
    return (
      <div>
        {this.elementSlot}
      </div>); }}export default HelloWorld;

Copy the code
  • Function component writing
/ / the parent component
import HelloWorld from './HelloWorld.js';

export default function Index(){
  const info = () = >{
    return (
      <span>hello World</span>)}return (
    <HelloWorld element={info}></HelloWorld>)}/ / child component
export default function HelloWorld(props) {
  const { children, element } = props;
  let elementSlot = "";
  if (element) {
    elementSlot = element();
  }
  return (
    <div>
      {elementSlot}
    </div>
  );
}
Copy the code

How to implement v-Model two-way data binding in React

This is done in a normal controlled component through the value and React composite event onChange

In custom commonware it is implemented by parent component communication and child component calling parent component methods.

React v-show

Needless to say, specify the style of the component when render (or return)

React v-if and React

Return different components via JS if and else

15. React v-for

Is implemented through the map function of the data, but be aware that elements in the map method need to be set with the key attribute, otherwise warning errors will be generated.

16. Life cycle

The life cycle of Vue components is divided into four stages: create, mount, update and destroy, and the respective hook functions will be triggered before and after each stage of the life cycle.

The React component life cycle is divided into mount, update, and uninstall phases. The most important thing to understand the life cycle is to know which hook functions are triggered in each phase of the life cycle.

1. Mount the React component

The React component mount phase calls the hook functions constructor/getDerivedStateFromProps/componentDidMount/Render in sequence

1.1 the constructor

Constructor is actually the constructor of a subclass of React.component. where we generally do three things.

  • Call super(props) before any other statement, otherwise this.props is undefined
  • Initialize state by assigning the this.state object;
  • Bind an instance to the event handler, otherwise this cannot be used in the function;

Two other points to note:

  • Internal state cannot be initialized with this.setState
  • You cannot assign props to state and then use state instead of props, because when the props is updated, the corresponding state is not updated

1.2 getDerivedStateFromProps

This is an uncommon hook function that derives a new state from the component’s props. The getDerivedStateFromProps hook function takes props and state of the component as arguments and returns either an object or null. If an object is returned, the object is used to update the state. If null is returned, the state is not updated

There are three points to note when using the getDerivedStateFromProps hook function:

  • To derive a new state, do not modify the original state
  • The function must return an object or NULL at the end
  • This cannot be used in hook functions.

1.3 render

The render function should be pure and should not modify the state and props in it. When writing React elements with JSX, the React element is bound to data using both state and props. Finally, some React elements must be returned, and these React elements must have only one root element. To avoid adding a useless tag to the DOM, use < react. Fragment> (or <>) as the root element

1.4 componentDidMount

ComponentDidMount is called immediately after the component is mounted (inserted into the DOM tree).

We can generally do the following operations:

  • Get the DOM element
  • Request server data
  • The listener event must be cancelled in compoentWillUnMount()
  • You can call this.setState() to change the state data

2. Update the React component

The React component update phase is called in sequence: GetDerivedStateFromProps, shouldComponentUpdate, Render, getSnapshotBeforeUpdate, componentDidUpdate etc.

React has three operations that cause component updates:

  • Component props changes
  • To perform this. SetState ()
  • This.forceupdate () : Forces the component to be rerendered; Executing it causes a component update, which passes through the shouldComponentUpdate hook function. But its children fire the normal lifecycle hook functions, including the shouldComponentUpdate hook function

2.1 getDerivedStateFromProps

This hook function is called during component mount and update phases, and the function receives state and props after the panel.

So the derived state is completely controlled by props, and this.setstate () doesn’t work

2.2 shouldComponentUpdate

ShouldComponentUpdate hook function to receive the updated state and props, through the comparison, and update the state and props to determine whether to update components, finally, returns true if the function is updated components, on the other hand; Generally used for performance optimization

The shouldComponentUpdate hook function needs to be used with the following points:

  • If this.forceUpdate() is invoked in a component to trigger a component update, the hook function is not executed
  • When this.setstate () is executed, it must be in a conditional statement, or it will get stuck in an infinite loop, causing the program to crash
  • Function must return true or false, if false, subsequent render, getSnapshotBeforeUpdate, componentDidUpdate hook functions are not called.

2.3 render

Don’t explain

2.4 getSnapshotBeforeUpdate

This hook function is equivalent to the beforeUpdate hook function in Vue; When this function is called, the props and state are updated, so it takes the props and state before the update as arguments for comparison.

The hook function returns a value that is received by the third parameter snapshot to componentDidUpdate;

This hook function is called after the component is rerendered and before it is mounted to the DOM. Therefore, the DOM obtained in this function is still the DOM before and after the update. Generally, the interaction operation before and after the component UI update is used

There are three points to note when using this function:

  • When this.forceUpdate or this.setState() is executed within it, it must be in a conditional statement, otherwise it will get stuck in an infinite loop
  • The function must return a value or NULL at the end, otherwise the code will report an error
  • Must be called with the componentDidUpdate hook function, otherwise an error is reported

2.5 componentDidUpdate

This hook function is executed after the component has been re-rendered and mounted into the DOM. The function parameters receive the state and props before the update, and the value returned by the getSnapshotBeforeUpdate hook function with the snapshot parameter

There are two points to note when using this function:

  • When this.forceUpdate or this.setState() is executed within it, it must be in a conditional statement, otherwise it will get stuck in an infinite loop
  • If the shouldComponentUpdate hook function returns false, this function is not called

3. Uninstall the React component

3.1 componentWillUnMount

Called before a component is destroyed, it typically does the following:

  • Clear timer
  • Canceling a network request
  • Unbind the componentDidMount hook function to listen for events

17. Optimize React component updates

React parent components are updated, regardless of whether the components’ state and props are changed. The React update mechanism can cause performance problems, so use the React.PureComponent to create a child component with a large update calculation unlock to optimize performance.

PureComponent creates a component that calls the shouldComponentUpdate hook function, so it cannot call the shouldComponentUpdate hook function again in this component.

ShouldComponentUpdate automatically compares props and state in the shouldComponentUpdate hook function, and returns true if the data changes to trigger the component update.

“Shallow comparison” : compares only one layer of the properties of this.props, such as arrays or objects, without comparing nested data inside. In other words, the value of an attribute is considered unchanged as long as the reference address of the attribute does not change. Arrays and objects are reference types.

The react. PureComponent child component is created in the parent component. Only when the props passed to the child component changes after a superficial comparison, can the child component update be triggered. This prevents the child component from being forced to update when the parent component data changes, thus optimizing the performance.

Alternatively, you can call this.forceUpdate to force child component updates.

The React function component life cycle

The Hook functions in the above documentation are not available in functional components, so you can simulate them using React Hook.

18.1 the constructor

Simulate constructor by deconstructing assignment with useState, which is not explained

If the initial value of state requires a complex set of calculations, you can pass a function to useState

const [amount , setAmount] = useState( () = >{
    returngetAmount(num); })Copy the code

The initial value of state is used when the component is mounted. To avoid calling getAmount again when the component is updated, wrap getAmount in () => {retur getAmount(num)}. Pass it to useState

18.2 getDerivedStateFromProps

18.3 render

Don’t explain

18.4 componentDidMount

UseEffect to simulate. Because the componentDidMount hook function is executed only once in the life of the component, to execute useEffect only once (only when the component is mounted), you can pass an empty array as the second argument to useEffect, and the first argument receives a function, Things that are executed in functions and componentDidMount hook functions.

18.5 shouldComponentUpdate

18.5.1 React. Memo simulation

The react. memo wraps a component to compare its props, and this component can only be a function component. This component is updated when its props change

The react. memo only checks the changes in the props of the packaged component. The memo does not compare the state of the component. If the state of the component is changed, the component update cannot be prevented.

const Hello = React.memo( (props) = >{})Copy the code

The comparison function uses the React. Memo parameter as the second parameter. The comparison function uses the props parameter before and after receiving the changes.

import React, {useEffect } from 'react';
const HelloWorld = React.memo((props) = >{
  const {num} = props;
  useEffect(() = >{
    console.log('update')})return(
    <div>{num}</div>)},(prevProps, nextProps) = >{
  / / update
  return false
  / / not updated
  return true
})
export default HelloWorld;
Copy the code

Update when the comparison function returns true to not update and false to update

18.5.2 useMemo Simulation

useMemo(() = > fn, deps)
Copy the code

The first argument to useMemo is a function. The second argument is an array containing the data to listen for. When the data changes, the first argument is reexecuted. In addition, useMemo returns the value of the first argument.

If a component is returned in the first argument function, the update of that component is controlled by the data in the second argument array, which indirectly implements the shouldComponentUpdate hook function.

But because you can’t use useState to define the state of a component in useMemo, you can only compare props to determine whether to update the component.

import React from 'react';
const HelloWorld = (props) = >{
  const {num} = props;
  return (
    <div>{num}</div>)}export default HelloWorld;


import React,{useMemo,useState} from 'react';
import HelloWorld from './HelloWorld';
const Index = (props) = >{
  const [num,setNum] = useState(1)
  const Hello = useMemo(() = >{
    return (
      <HelloWorld num={num}></HelloWorld>
    )
  },[num])

  return (
    <div>
      {Hello}
    </div>)}export default Index;
Copy the code

The HelloWorld component above will only be updated if num’s prop changes.

When using useMemo to wrap a component, the props used in the component must be added to the second parameter array. Otherwise, when the props is updated, the props in the component is still old.

18.5.3 Simulation with useCallbacl

The difference between useCallback and useMemo is. UseCallback returns a function, useMemo returns a value.

The first argument to useCallback is a function that useCallback returns. The second argument is an array of the data to listen for, and the first argument is returned when the data changes.

If the first argument function is a function component, the update of that component is controlled by the data in the second argument array, which indirectly implements the shouldComponentUpdate hook function.

import React from 'react';
const HelloWorld = (props) = >{
  const {num} = props;
  return (
    <div>{num}</div>)}export default HelloWorld;


import React,{useCallback,useState} from 'react';
import HelloWorld from './HelloWorld';
const Index = (props) = >{
  const [num,setNum] = useState(1)
  const Hello = useCallback(() = >{
    return (
      <HelloWorld num={num}></HelloWorld>
    )
  },[num])

  return (
    <div>
      {Hello()}
    </div>)}export default Index;
Copy the code

The HelloWorld component is handled with useMemo and useCallback respectively, returning Hello. The only difference with useCallback is that {Hello()} uses the HelloWorld component like this. UseCallback (fn, deps) is equivalent to useMemo(() => FN, deps).

When wrapping a component with useCallback, the props that are useful in the component must be added to the array as the second parameter. Otherwise, when the props is updated, the props in the component is still old.

Analog componentDidUpdate

The first argument to useEffect takes a function, and the second argument is an array to which props or state are added to listen. The first argument to useEffect is executed when the props or state of the listener changes. You can put the code to be executed in componentDidUpdate hook function in useEffect’s first argument function.

import React,{useState} from 'react';
const HelloWorld = (props) = >{
  const [num,setNum]=useState(1);
  const changNum = () = >{
      setNum(2);
  }
  useEffect(() = >{
    console.log('num data changed ')
  },[num])
  return (
    <div onClick={changNum}>{num}</div>)}export default HelloWorld;
Copy the code

Simulate componentWillUnmount

Consistent with the information in #19

21. Communication between components

React components have parent-child relationships, cross-level relationships, and non-nested relationships.

21.1 Father-son relationship

  • The parent component communicates with the child component by assigning the parent component’s state to the props of the child component.
  • The functions of the parent component that change its own data are assigned to the props of the child component, and this function is called in the child component to realize the communication between the child component and the parent component

21.2 Cross-level relationship

In Vue, provide/inject is implemented. React also has a similar function called Context.

Context provides a way to pass data across the component tree without manually adding props for each layer of components

Use React. CreateContext to create a context, and then use context. Provider to inject some data into the ancestor component. This data is then retrieved in a descendant component using either class. contextType or context.consumer.

  • Class component writing

Create a context in context.js

import React from 'react'   
export const MyContext = React.createContext(
    // Here you can set some defaults
    {
        title: 'hello world'})Copy the code

Reference MyContext in the ancestor component, then wrap the child component Father with myContext.provider and assign the “value” to the property value on myContext.proivder, which is equivalent to injecting data

import React from 'react';
import Father from './Father.js';
import { MyContext } from './context.js';
export default class Grandfather extends React.Component {
  constructor(){
    super(a);this.state={
      info: {title:'hello react'}}}render() {
    return (
      <MyContext.Provider value={this.state.info}>
        <Father>
        </Father>
      </MyContext.Provider>)}}// Add the Son component to the Father component
import React from 'react';
import Son from './Son.js';
export default class Father extends React.Component{
  render(){
    return(
      <Son></Son>)}}Copy the code

At this point, the component Son is a descendant of the component Grandfather. Parent (props); Son (props); Father (props); Son (props)

In the class component, MyContext is assigned to the static contextType property in the class component, This. Context is then used to retrieve the value of the property passed to myContext. Provider from the parent component of the component that was recently wrapped by MyContext.Provider.

import React from 'react';
import { MyContext } from './context.js';
export default class Son extends React.Component {
  static contextType = MyContext;
  render() {
    return (
      <div>
        {this.context.title}
      </div>)}}Copy the code
  • Functional component

Inside the function component, wrap a functional component with myContext.consumer, whose arguments, Can receive the data passed to the myContext. Provider property value from the parent component of the component that was recently wrapped by MyContext.Provider.

import React from 'react';
import { MyContext } from './context.js';
export default class Son extends React.Component {
  static contextType = MyContext;
  render() {
    return (
      <MyContext.Consumer>
        {value => (<div>{value.title}</div>)}
      </MyContext.Consumer>)}}Copy the code

Remember to create a Context with React. CreateContext, which accepts some data as default. If none of the parent components of a component that uses class. contextType or context. Consumer are wrapped with myContext. Provider, then this. Context and value get the default data.

21.3 Non-nested React Component Communication

Use common components, not explained

21.4 the Event Bus

React does not provide apis like Vue vM.onvm.on vm.onvm.off vm. $emit, but node.js event.js can be used to implement it.

First run NPM install Events -s to download and install.

Create eventBus.js, import Event.js, and create an Instance of EventEmitter.

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

EventEmitter instances provide instance methods like vm.on, vm.on, vM. off, and vM. $emit.

Emitter. On (eventName, listener) corresponds to vm.$on(event, callback);

Emitter. Off (eventName, listener) corresponds to vm.$off([event, callback]);

Emitter. Emit (eventName[…args]) corresponds to vm.$emit(eventName, […args]);

EventName is the name of the event to listen for, and listener is the callback function of the event to listen for… Args The argument passed to the callback of the listening event.

So, for example, two non-nested components A and B can also communicate through events.js. We can bind events to be monitored in the mount phase of component A with Emitters. Emit the monitored event with emitters in component B, and pass the parameter starting from emitters second parameter as the parameter to the callback function of the monitoring event bound to Emitters. On, that is, realize the function of receiving the data from component B to component A.

Implementation of function components:

Component A

import React,{useEffect} from 'react';
import emitter from "./ev"
const A = () = >{
  const handleChange = (param1,param2) = >{
    console.log(param1);
    console.log(param2);
  }
  useEffect(() = >{
    emitter.on('chang',handleChange);
    return () = >{
      emitter.off('chang',handleChange);
    }
  },[])
  return(
    <div>A component</div>)}export default A;

Copy the code

The component B:

import React from 'react';
import emitter from "./ev"
const B = () = >{
  const handleChange = () = >{
    emitter.emit('chang'.Parameters' 1 '.Parameters' 2 ')}return(
    <div onClick={handleChange}>B component</div>)}export default B;
Copy the code

React Family bucket configuration

React Family bucket Reference address