1: React.lazy and react. Suspense encapsulate dynamic functions to introduce components dynamically

1: Basic use

// How to use it
import React, {Component} from 'react';
import {dynamic} from './utils';

const LoadingHome = dynamic(() = > import('./components/Home'));
const LoadingUser = dynamic(() = > import('./components/User'));

class App extends Component {
    state = {
        showHome: false.showUser: false
    }
    toggle = (key) = > {
        this.setState({
            [key]: !this.state[key]
        })
    }
    render() {
        let {showHome, showUser} = this.state
        return (
            <div>
                {showHome && <LoadingHome/>}
                {showUser && <LoadingUser/>}
                <button onClick={()= > this.toggle('showHome')}>showHome</button>
                <button onClick={()= > this.toggle('showUser')}>showUser</button>
            </div>); }}export default App;
Copy the code
// Encapsulates the dynamic function
import React from 'react';
const Loading = () = > <div>Loading</div>;

export function dynamic(loadComponent) {
    const LazyComponent = React.lazy(loadComponent)
    return () = > (
        <React.Suspense fallback={<Loading />} ><LazyComponent />
        </React.Suspense>)}Copy the code

2: Analysis of lazy principle

function lazy(load) {
    return class extends React.Component {
        state = { Component: null }
        componentDidMount() {
            load().then(result= > {
                this.setState({ Component: result.default});
            });
        }
        render() {
            let { Component } = this.state;
            return Component && <Component />; }}}Copy the code

2: PureComponent, Memo resolves invalid render issues

1: PureComponent. The memo is basically used

import React,{PureComponent,memo,Component} from 'react';
export default class App extends React.Component{
    constructor(props){
        super(props);
        this.state = {title:'counter'.number:0}
    }
    add = (amount) = >{
        this.setState({number:this.state.number+amount});
    }
    render(){
        console.log('App render');
        return (
            <div>
                <Counter number={this.state.number}/>
                <button onClick={()= >this.add(1)}>+1</button>
                <button onClick={()= >this.add(0)}>+0</button>
                <ClassTitle title={this.state.title}/>
                <FunctionTitle title={this.state.title}/>
            </div>)}}class Counter extends Component{
    render(){
        console.log('Counter render');
        return (
            <p>{this.props.number}</p>)}}class ClassTitle extends Component{
    render(){
        console.log('ClassTitle render');
        return (
            <p>{this.props.title}</p>)}}const FunctionTitle = function (props) {
    console.log('FunctionTitle render');
    return  <p>{props.title}</p>;
}
Copy the code

As long as the parent component setstate, the child component, whether class component or functional component, will render regardless of whether the props changes. This is obviously not appropriate. Therefore, React comes with two things: PureComponent,memo

import React,{PureComponent,memo,Component} from 'react';
export default class App extends React.Component{
    constructor(props){
        super(props);
        this.state = {title:'counter'.number:0}
    }
    add = (amount) = >{
        this.setState({number:this.state.number+amount});
    }
    render(){
        console.log('App render');
        return (
            <div>
                <Counter number={this.state.number}/>
                <button onClick={()= >this.add(1)}>+1</button>
                <button onClick={()= >this.add(0)}>+0</button>
                <ClassTitle title={this.state.title}/>
                <FunctionTitle title={this.state.title}/>
            </div>)}}class Counter extends PureComponent{
    render(){
        console.log('Counter render');
        return (
            <p>{this.props.number}</p>)}}class ClassTitle extends PureComponent{
    render(){
        console.log('ClassTitle render');
        return (
            <p>{this.props.title}</p>)}}const FunctionTitle = memo(props= >{
    console.log('FunctionTitle render');
    return  <p>{props.title}</p>;
});
Copy the code

So that either the class component or the functional component is not rendering as long as the props are not changing

2: Let’s implement PureComponent manually, Memo

import React from 'react';
export class PureComponent extends React.Component{
   shouldComponentUpdate(nextProps,nextState){
       return! shallowEqual(this.props,nextProps)||! shallowEqual(this.state,nextState)
   }
}
export function memo(OldComponent){
   return class extends PureComponent{
     render(){
       return <OldComponent {. this.props} / >}}}export function shallowEqual(obj1,obj2){
   if(obj1 === obj2)
       return true;
   if(typeofobj1 ! = ='object' || obj1 ===null || typeofobj2 ! = ='object' || obj2 ===null) {return false;
   }    
   let keys1 = Object.keys(obj1);
   let keys2 = Object.keys(obj2);
   if(keys1.length ! == keys2.length){return false;
   }
   for(let key of keys1){
       if(! obj2.hasOwnProperty(key) || obj1[key]! == obj2[key]){return false; }}return true;
}
Copy the code

Isn’t it interesting 😄