React learning notes -- the difference between the setState of Function components and Class components

Posted by Whitestripes9805 on Wed, 22 Dec 2021 09:28:29 +0100

I think we all know the similarities and differences between Function components and Class components in React, such as:

1. Same point

  • Whether a component is declared using a function or class, it must not modify its own props
  • All React components must be pure functions, and it is forbidden to modify their own props
  • React is a single data flow. If the parent component changes its properties, the child component view will be updated
  • When the parent component props changes, the child components change accordingly
  • The property props is passed from the outside, the state state is the state of the component itself, and the state can be modified arbitrarily in the component
  • Changes in the properties and state of the component update the view.

2. Different points

differenceFunction componentClass component
life cycleNo,have
thisNo,have
stateNo,have
Change stateHook: useStatethis.setState()
performanceHigh (no instantiation)Low (instantiation required)

3. Case

(1) class component

However, my colleague asked me a simple code question today. I didn't think about it seriously before and didn't answer it all at once.
Without much to say, let's take a look:

import React, { Component } from 'react'
class App extends Component {
    state={
        number:0
    }
    handleClick=()=>{
       for(let i = 0 ;i<5;i++){
           setTimeout(()=>{
               this.setState({ number:this.state.number+1 })
               console.log(this.state.number)
           },1000)
       }
    }
    render(){
        return(
            <div>
                Current number: {this.state.number}
                <button onClick={this.handleClick}>Click me</button>
            </div>
        )
    }
}
export default App

(2) Function component

import React ,{ useState } from 'react';
const App = () => {
    const [ num ,setNumber ] = useState(0)
    const handleClick1 = ()=> {
        for(let i=0; i<5;i++ ){
           setTimeout(() => {
                setNumber(num+1)
                console.log(num)
           }, 1000)
        }
    }
    return (
        <div>
            Current num Value:{num}
            <br/>
            <button onClick={handleClick1}>change num</button>
        </div>
    );
};
export default App;

(3) Comparison results

It can be seen that:
For the first class component, the print result is: 1 2 3 4 5, and 5 is displayed on the page;
For the second Function component, the print result is 0, and 1 is displayed on the page

This result looks frightening. Analyze it carefully:

  • In a class component, an instantiated class is used to maintain various states in the component. Click the button and cycle the setTimeout five times. At the same time, because the setState is not in the execution context of the normal react function, but in the asynchronous setTimeout, the conditions for batch update are destroyed and the values after each setState can be obtained synchronously
    (for batch update of React, you can view: React learning notes - this The basic use of setState and the different methods of simultaneous interpreting)
  • In the Function component, there is no state to save this information. It is just a Function. Every time the Function context is executed, all variables and constants are redeclared. After execution, they are recycled by the garbage mechanism. Therefore, as described above, no matter how many times setTimeout is executed, it is executed in the current Function context. At this time, num = 0 will not change. Then setNumber is executed, and num will change only after the Function component is re executed.

Conclusion:

  • Therefore, we only need to instantiate the class component once, and the state of the component is saved in the instance. For each update, you only need to call the render method.
  • However, in the function component, every update is a new function execution. In order to save some states and execute some side effects hooks, react hooks came into being to help record the state of the component and deal with some additional side effects.

4. Interesting expansion

For the writing of Function, there are two writing methods of Function and object in set. Let's observe the differences between the two methods:

import React ,{ useState } from 'react';
const App = () => {
    const [ num ,setNumber ] = useState(0)
    const [ val ,setVal ] = useState(0)
    const handleClick1 = ()=> {
        for(let i=0; i<5;i++ ){
           setTimeout(() => {
                setNumber(num+1)
                console.log('num',num)
                
           }, 1000)
        }
    }
    const handleClick2 = () =>{
        for(let i=0; i<5;i++ ){
            setTimeout(() => {
                 setVal(val=>val+1)
                 console.log('val',val)
            }, 1000)
        }
    }
    return (
        <div>
            Current num Value:{num}
            <br/>
            <button onClick={handleClick1}>change num</button>
            <br/>
            Current val Value:{val}
            <br/>
            <button onClick={handleClick2}>change val</button>
        </div>
    );
};
export default App;


It can be seen that when it is written in functional form, although the val value printed each time is 0, it will depend on the last state, so the val value will be + 1 every time; The object-oriented writing method does not.

Topics: React