The following code all runs in the React scaffolding environment

Consolidation of higher-order components

import React from 'react'
import ReactDOM from 'react-dom'
import Cat from './Cat'
import Position from './Position'

// Component Cat and component Position, both of which require x,y with mouse changes
// Advanced components: (Decoration mode)
// 1. The higher-order component is a function, starting with with
// 2. If a component is passed in, a new component is returned
// 3. A new component will be created based on this component, and reuse functions will be implemented in the new component
function withMouse(Base) {
  class Mouse extends React.Component {
    state = {
      x: 0.y: 0,}render() {
      return <Base {. this.state} ></Base>
    }
    componentDidMount() {
      document.addEventListener('mousemove'.this.handleMove.bind(this))}handleMove(e) {
      this.setState({
        x: e.clientX,
        y: e.clientY,
      })
    }
  }
  return Mouse
}

const CatWithMouse = withMouse(Cat)
const PositionWithMouse = withMouse(Position)

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>This is the app component</h1>
        <CatWithMouse></CatWithMouse>
        <PositionWithMouse></PositionWithMouse>
      </div>
    )
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code
//Cat.js
import React from 'react'
import Img from './cat.png'

class Cat extends React.Component {
  static defaultProps = {
    x: 64.y: 64.money: 0,}render() {
    return (
      <div>
        <img
          style={{
            position: 'fixed',
            left: this.props.x - 64.top: this.props.y - 64,}}src={Img}
          alt=""
        />
        <p>I am cat component, my money: {this.props. Money}</p>
      </div>)}}export default Cat

Copy the code
//Postion.js
import React from 'react'

class Position extends React.Component {
  static defaultProps = {
    x: 64.y: 64.money: 0,}render() {
    return (
      <div>(x: {this.props. X}, y: {this.props. Y})<p>I am position component, my money: {this.props. Money}</p>
      </div>)}}export default Position

Copy the code

Problems with props missing

import React from 'react'
import ReactDOM from 'react-dom'
import Cat from './Cat'
import Position from './Position'

// Component Cat and component Position, both of which require x,y with mouse changes
// Advanced components: (Decoration mode)
// 1. The higher-order component is a function, starting with with
// 2. If a component is passed in, a new component is returned
// 3. A new component will be created based on this component, and reuse functions will be implemented in the new component
function withMouse(Base) {
  class Mouse extends React.Component {
    state = {
      x: 0.y: 0,}render() {
      // Once processed with higher-order components, a layer of components is wrapped around the original component
      // If we pass to props, we are passing to the outer component and need to pass down
      return <Base {. this.state} {. this.props} ></Base>
    }
    componentDidMount() {
      document.addEventListener('mousemove'.this.handleMove.bind(this))}handleMove(e) {
      this.setState({
        x: e.clientX,
        y: e.clientY,
      })
    }
  }
  return Mouse
}

const CatWithMouse = withMouse(Cat)
const PositionWithMouse = withMouse(Position)

// Props missing problem: After high-level component encapsulation, there is a problem that props is missing, which needs to be solved
// Solution: When encapsulating higher-order components, props also need to be passed down
class App extends React.Component {
  render() {
    return (
      <div>
        <h1>This is the app component</h1>
        <CatWithMouse></CatWithMouse>
        <PositionWithMouse money={5000}></PositionWithMouse>
        <Position x={100} y={100} money={2000}></Position>
      </div>
    )
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code

Higher-order component name -diaplayName

import React from 'react'
import ReactDOM from 'react-dom'
import Cat from './Cat'
import Position from './Position'

// Component Cat and component Position, both of which require x,y with mouse changes
// Advanced components: (Decoration mode)
// 1. The higher-order component is a function, starting with with
// 2. If a component is passed in, a new component is returned
// 3. A new component will be created based on this component, and reuse functions will be implemented in the new component
function withMouse(Base) {
  class Mouse extends React.Component {
    state = {
      x: 0.y: 0,}render() {
      // Once processed with higher-order components, a layer of components is wrapped around the original component
      // If we pass to props, we are passing to the outer component and need to pass down
      return <Base {. this.state} {. this.props} ></Base>
    }
    componentDidMount() {
      document.addEventListener('mousemove'.this.handleMove.bind(this))}handleMove(e) {
      this.setState({
        x: e.clientX,
        y: e.clientY,
      })
    }
  }
  // displayName controls the name of the component displayed during console debugging
  // Name is the component name
  Mouse.displayName = `${Base.displayName || Base.name}WithMouse`
  return Mouse
}

// Define a higher-order component that handles the logic of random money
function withMoney(Base) {
  class Money extends React.Component {
    state = {
      money: 0,}render() {
      return <Base {. this.state} {. this.props} ></Base>
    }
    componentDidMount() {
      this.setState({
        money: parseInt(Math.random() * 100000),})}}// Use the console displayName defined first, if not the component name
  Money.displayName = `${Base.displayName || Base.name}WithMoney`
  return Money
}

const CatWithMouse = withMoney(withMouse(Cat))
const PositionWithMouse = withMoney(withMouse(Position))

// Props missing problem: After high-level component encapsulation, there is a problem that props is missing, which needs to be solved
// Solution: When encapsulating higher-order components, props also need to be passed down
class App extends React.Component {
  render() {
    return (
      <div>
        <h1>This is the app component</h1>
        <CatWithMouse></CatWithMouse>
        <PositionWithMouse></PositionWithMouse>
      </div>
    )
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code

SetState is asynchronous

import React from 'react'
import ReactDOM from 'react-dom'

// setState:
// 1. Modify state
// 2. Update the view to trigger the update
// Note that setState is asynchronous

// 1. When we setState, react.js does not immediately change state (for performance)
// 2. If there are multiple setStates, those operations will be added to a queue
// 3. Finally, merge the states uniformly and update the view once, only rendering once
// 4. So, don't worry about the performance of calling setState multiple times
// Note: the following setState does not depend on the result of the previous setState

class App extends React.Component {
  state = {
    count: 0.money: 0,}render() {
    return (
      <div>
        <h1>This is the app component</h1>
        <p>count: {this.state.count}</p>
        <p>money: {this.state.money}</p>
        <button onClick={this.handleClick.bind(this)}>button</button>
      </div>)}handleClick() {
    // Multiple calls to setState will eventually be merged into one operation
    // this.setState({
    // count: this.state.count + 1,
    // })
    // this.setState({
    // money: 100,
    // })
    // ------------------------------------------------------
    // Use setState several times, but the subsequent setState must not depend on the results of the previous setState
    this.setState({
      count: this.state.count + 1,})this.setState({
      count: this.state.count + 1,})this.setState({
      count: this.state.count + 1,})console.log(this.state.count) / / 0
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code

SetState passes in a function

import React from 'react'
import ReactDOM from 'react-dom'

/ / a setState syntax
// 1. setState(object) should not depend on the result of previous setState when called multiple times
// 2. SetState (function) is passed in the form of a function that returns an object. Subsequent setState can depend on the result of previous setState
// this.setState((prevState) => {
/ / return objects
/ /})

class App extends React.Component {
  state = {
    count: 0.money: 0,}render() {
    return (
      <div>
        <h1>This is the app component</h1>
        <p>count: {this.state.count}</p>
        <p>money: {this.state.money}</p>
        <button onClick={this.handleClick.bind(this)}>button</button>
      </div>)}handleClick() {
    this.setState((prevState) = > {
      return {
        count: prevState.count + 1,}})this.setState((prevState) = > {
      return {
        count: prevState.count + 1,}})this.setState((prevState) = > {
      return {
        count: prevState.count + 1,
      }
    })
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code

SetState passes a callback

import React from 'react'
import ReactDOM from 'react-dom'

/ / a setState syntax
// 1. setState(object, callback) when called multiple times, subsequent setState should not depend on the result of previous setState
// 2. SetState (function, callback) is passed in the form of a function that returns an object. Subsequent setState can depend on the result of previous setState
// this.setState((prevState) => {
/ / return objects
/ /})

Note that the second argument, the callback function, indicates that state is set, DOM is updated, and execution is completed

class App extends React.Component {
  state = {
    count: 0.money: 0,}render() {
    return (
      <div>
        <h1>This is the app component</h1>
        <p id="box">count: {this.state.count}</p>
        <p>money: {this.state.money}</p>
        <button onClick={this.handleClick.bind(this)}>button</button>
      </div>)}handleClick() {
    // Requirement: You want to get the modified result
    // setState is asynchronous
    this.setState(
      (prevState) = > {
        return {
          count: prevState.count + 1,}},// The second argument, the callback function, is executed after the state update is complete and dom rendering is complete
      () = > {
        console.log(this.state.count)
        console.log(document.getElementById('box').innerHTML)
      }
    )
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code

JSX substance -JS object – React element

import React from 'react'
import ReactDOM from 'react-dom'

// JSX syntax: essentially create the React element at the React. CreateElement
// A JSX structure can be viewed as a react element, which is essentially a JS object that describes a DOM structure (not a real DOM).
// const element = 

const element = React.createElement('h1'.null.'I am the headline') console.log(element) // const h1 = document.createElement('h1') // h1.innerText = 'I am the title' // console.dir(h1) ReactDOM.render(element, document.getElementById('root')) Copy the code

Understanding the virtual DOM

// Virtual DOM: is a JS object that describes the real DOM structure
/ / features:
// 1. React will update the view for us when setState is set
// 2. The efficiency of the update is very high, and the update is differentiated (which side is changed, where is updated).
// --------------------------------------------------------------------------
// Start with a page, using template + data to generate the structure, and then render the view with the structure

// 1. If there is no virtual DOM, what is the process of direct update
1.1 Preparing the TEMPLATE JSX structure
1.2 Preparing Data State data
// 1.3 Generate DOM structure from template and data
// 1.4 Render the page using DOM structure

// 1.5 Data changes
// 1.6 Generate a new DOM structure based on templates and new data
// 1.7 Use the new DOM structure directly, replace the original structure, render (directly, completely replaced)
// Problem: In fact, it is not necessary to replace all parts, only the changed parts need to be updated. Replacing all parts is inefficient
// -----------------------------------------------------------------------------
// 2. You can compare the changed PARTS of the DOM and update only the changed parts
2.1 Preparing the TEMPLATE JSX structure
2.2 Preparing data in Data State
// 2.3 Generate DOM structures from templates and data
// 2.4 Use DOM structure to render pages

// 2.5 Data changes
// 2.6 Generate new DOM structures from templates and new data
// 2.7 Compare the new DOM structure with the old dom structure, just update the changed part
// Problem: Great idea, but difficult to compare to the dom structure (dom structure is too complex, there are a lot of attributes)

// -----------------------------------------------------------------------------
// 3. Virtual DOM: is a JS object that describes the STRUCTURE of the DOM.
// Vue and React are using the same strategy as the virtual DOM
// 3.1 Preparing the TEMPLATE JSX structure
// 3.2 Preparing data in data State
// 3.3 Generate virtual DOM based on template and data
// 3.4 Generate real DOM based on virtual DOM for rendering

// 3.5 Data has changed
3.6 Generate a new virtual DOM based on the template and new data
// 3.7 Compare the old and new virtual DOM (the virtual DOM is a JS object that describes the real DOM but is much simpler)
// 3.8 Update the view according to the differences between the old and new DOM
// Features: It looks like more virtual DOM manipulation, but in fact, greatly improved contrast and rendering performance, achieve differentiation update

// --------------------------------------------------------------------------------------
// Even with the virtual DOM, the actual comparison between the old and new DOM is quite complicated and requires a certain algorithm to be followed
// Follow the diff algorithm

// Dom structure is a tree structure
// The virtual DOM is an object that describes the real DOM structure. It should also be a tree structure
// Tree structure traversal, each layer down, will consume more performance, need to improve the efficiency of comparison as much as possible
// Diff algorithm strategy:
// 1. tree diff
// 2. component diff
// 3. element diff

import React from 'react'
import ReactDOM from 'react-dom'

const element1 = <div>I am the div1</div>
const element2 = <div>I am div2</div>
console.log(element1)
console.log(element2)

class App extends React.Component {
  state = {
    count: 0,}render() {
    return (
      <div>
        <h1>I'm an App component</h1>
        <p>count: {this.state.count}</p>
        <button onClick={this.handleClick.bind(this)}>Change the value</button>
      </div>)}handleClick() {
    this.setState({
      count: this.state.count + 1,
    })
  }
}

ReactDOM.render(<App></App>.document.getElementById('root'))

Copy the code

Diff algorithm strategy

// Dom structure is a tree structure
// The virtual DOM is an object that describes the real DOM structure. It should also be a tree structure
// Tree structure traversal, each layer down, will consume more performance, need to improve the efficiency of comparison as much as possible

// Strategies of the diff algorithm: These three strategies are used in sequence in comparison
// 1. tree diff
// 2. component diff
// 3. element diff

// 1. tree diff
// Compare each layer of the tree, from top to bottom. If the element type is different, destroy it and rebuild it
// Benefits: the whole tree can be compared once (this is simple and efficient) reuse across levels is not considered
// const element1 = (
// 
      
// // // ) // const element2 = ( //

// //

// ) // 2. component diff // If the corresponding element type of the same layer is the same, keep the DOM node // The attributes of the old and new virtual DOM elements are compared, and the changes are recorded // React performs recursive comparisons on child nodes after processing the current layer node // const element1 = ( //
// // // ) // const element2 = ( //
//

I am h1 element

// // ) // 3. element diff // (1) All child nodes of the same parent element are compared in order by default // (efficient, reasonable, normal page rendering order is not likely to change) // const element1 = ( //
//

I am h1 element

// // // ) // const element2 = ( //
//

I'm an H1 element - gaga

// // // ) // (2) If it is a list rendering, it is possible to change the order, or use the subscript comparison, performance is not high!! // If an item is added to the front of the list, the order of the entire list changes, and the key attribute needs to be added to improve the comparison performance // Key adds a unique identity to the virtual DOM // As long as the key attribute is configured, the child nodes of the same layer are not compared according to the subscript, but are compared according to the key first // Benefits: greatly improved virtual DOM corresponding efficiency, thereby improving page rendering performance, reuse the previous list structure!! // const element1 = ( //
    //
  • //
  • // // ) // const element2 = ( //
      //
    • //
    • //
    • // // ) import React from 'react' import ReactDOM from 'react-dom' // const element1 =
      // const element2 =
      // console.log(element1) // console.log(element2) class App extends React.Component { state = { count: 0,}render() { return ( <div> <h1>I'm an App component</h1> <p>count: {this.state.count}</p> <button onClick={this.handleClick.bind(this)}>Change the value</button> </div>)}handleClick() { this.setState({ count: this.state.count + 1, }) } } ReactDOM.render(<App></App>.document.getElementById('root')) Copy the code

      React update rules

      // React update rule:
      // React components are updated, all component subtrees of the current component are rerendered (child nodes, children of child nodes....)
      
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class App extends React.Component {
        state = {
          count: 0,}render() {
          console.log('App-render')
          return (
            <div>
              <h1>I'm an App component</h1>
              <Father1></Father1>
              <Father2></Father2>
            </div>)}}class Father1 extends React.Component {
        state = {
          money: 100,}render() {
          console.log('Father1-render')
          return (
            <div>
              <h2>I'm the Father1 component</h2>
              <Child1></Child1>
              <Child2></Child2>
            </div>)}}class Child1 extends React.Component {
        render() {
          console.log('Child1-render')
          return (
            <div>
              <h3>I am a Child1 component</h3>
            </div>)}}class Child2 extends React.Component {
        render() {
          console.log('Child2-render')
          return (
            <div>
              <h3>I am a Child2 component</h3>
            </div>)}}class Father2 extends React.Component {
        render() {
          console.log('Father2-render')
          return (
            <div>
              <h2>I'm the Father2 component</h2>
              <Child3></Child3>
              <Child4></Child4>
            </div>)}}class Child3 extends React.Component {
        render() {
          console.log('Child3-render')
          return (
            <div>
              <h3>I am Child3 component</h3>
            </div>)}}class Child4 extends React.Component {
        render() {
          console.log('Child4-render')
          return (
            <div>
              <h3>I am Child4 component</h3>
            </div>
          )
        }
      }
      ReactDOM.render(<App></App>.document.getElementById('root'))
      
      Copy the code

      Performance optimization – Lightens state

      // React update rule:
      // React components are updated, all component subtrees of the current component are rerendered (child nodes, children of child nodes....)
      
      // Component performance optimization:
      // 1. Reduce state
      // setState, the current component and all component subtrees, are updated
      // Reduce state as much as possible, state only stores contents related to view rendering (count, list, obj)
      // View-independent objects, such as timer ids, should not be placed in state
      
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class App extends React.Component {
        state = {
          count: 0,}render() {
          console.log('App-render')
          return (
            <div>
              <h1>I'm an App component</h1>
              <Father1></Father1>
              <Father2></Father2>
            </div>)}componentDidMount() {
          this.timeId = setInterval(() = > {
            console.log('I'm a timer. I'm on.')},500)}componentWillUnmount() {
          // Release some related resources
          clearInterval(this.timeId)
        }
      }
      class Father1 extends React.Component {
        state = {
          money: 100,}render() {
          console.log('Father1-render')
          return (
            <div>
              <h2>I'm the Father1 component</h2>
              <Child1></Child1>
              <Child2></Child2>
            </div>)}}class Child1 extends React.Component {
        render() {
          console.log('Child1-render')
          return (
            <div>
              <h3>I am a Child1 component</h3>
            </div>)}}class Child2 extends React.Component {
        render() {
          console.log('Child2-render')
          return (
            <div>
              <h3>I am a Child2 component</h3>
            </div>)}}class Father2 extends React.Component {
        render() {
          console.log('Father2-render')
          return (
            <div>
              <h2>I'm the Father2 component</h2>
              <Child3></Child3>
              <Child4></Child4>
            </div>)}}class Child3 extends React.Component {
        render() {
          console.log('Child3-render')
          return (
            <div>
              <h3>I am Child3 component</h3>
            </div>)}}class Child4 extends React.Component {
        render() {
          console.log('Child4-render')
          return (
            <div>
              <h3>I am Child4 component</h3>
            </div>
          )
        }
      }
      ReactDOM.render(<App></App>.document.getElementById('root'))
      
      Copy the code

      Performance optimization – Avoid unnecessary updates

      // React update rule:
      // React components are updated, all component subtrees of the current component are rerendered (child nodes, children of child nodes....)
      
      // Component performance optimization:
      // 1. Reduce state
      // setState, the current component and all component subtrees, are updated
      // Reduce state as much as possible, state only stores contents related to view rendering (count, list, obj)
      // View-independent objects, such as timer ids, should not be placed in state
      
      // 2. Avoid unnecessary updates whenever possible
      // shouldComponentUpdate(nextProps) returns a Boolean, true to update, false not to update
      
      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class App extends React.Component {
        state = {
          count: 0.money: 100,}render() {
          console.log('App-render')
          return (
            <div>
              <h1>I'm an App component</h1>
              <Father1 count={this.state.count}></Father1>
              <Father2 money={this.state.money}></Father2>
            </div>)}}class Father1 extends React.Component {
        render() {
          console.log('Father1-render')
          return (
            <div>
              <h2>I am Father1 component - {this.props. Count}</h2>
            </div>)}}class Father2 extends React.Component {
        render() {
          console.log('Father2-render')
          return (
            <div>
              <h2>I am Father2 component - {this.props. Money}</h2>
            </div>)}// The current props pass hasn't changed, so Father2 doesn't need to be re-rendered
        // Can avoid some unnecessary updates
        // There is a hook function shouldComponentUpdate that returns a Boolean value, true to update, false not to update
        // Note: shouldComponentUpdate is not used to block updates, it is used to avoid unnecessary updates
        shouldComponentUpdate(nextProps) {
          // this. Props
          // nextProps Props to be updated
          // console.log(this.props, nextProps)
          // Compare the old and new props, if the props are changed, and if the props are not changed, they are not updated
          if (this.props.money === nextProps.money) {
            return false
          } else {
            return true
          }
        }
      }
      ReactDOM.render(<App></App>.document.getElementById('root'))
      
      Copy the code

      Random case

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      class App extends React.Component {
        state = {
          nameList: ['ShuaiPeng'.'lyu3 bu4'.'zhang fei'].currentName: ' ',}render() {
          console.log('App-render')
          return (
            <div>
              <h1>I'm an App component</h1>
              <h3>Results: {this. State. CurrentName}</h3>
              <button onClick={this.handleClick.bind(this)}>Call the roll</button>
            </div>)}handleClick() {
          const randomIndex = parseInt(Math.random() * this.state.nameList.length)
          const currentName = this.state.nameList[randomIndex]
      
          this.setState({
            currentName,
          })
          console.log(currentName)
        }
      
        // Requirement: If the value of state does not change, it does not need to be updated to avoid unnecessary updates
        shouldComponentUpdate(nextProps, nextState) {
          if (this.state.currentName === nextState.currentName) {
            return false
          } else {
            return true
          }
        }
      }
      ReactDOM.render(<App></App>.document.getElementById('root'))
      
      Copy the code