SetState () two ways to update the state

  1. setState(updater,[callback])

    Updater is the object of the function that returns stateChange, (state,props) => stateChange

    The received state and props are guaranteed to be up to date

    Function mode:

    1, if the new state depends on the original statethis.setState((state,props) = > ({
       count: state.count+1= > {}), ()// callback
    })
    Copy the code
  2. setState(stateChange,[callback])

StateChange as an object

Callback is an optional callback function that is executed after a status update and an interface update

Object mode:

1The new state does not depend on the original state ==> Use object modethis.setState({count:this.state.count+1= > {}, ()// callback
})
Copy the code

case

<body> <script src="https://unpkg.com/react@16/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script SRC ="https://unpkg.com/[email protected]/babel.js"></script> <div id="root"></div> <script type="text/ Babel "> class App extends React.Component { constructor(props) { super(props); This. state = {count:0}} test1 = ()=> {// If the new state is dependent on the original state, use the function this.setState((state,props)=> ({count:0}). State.count +1})) console.log('test1 ',this.state.count); // 0} test2 = ()=> {// New state does not depend on old state ==> const count = this.state.count + 1; this.setState({count}); Console. log(' get count after test2: ',this.state.count); } test3 = ()=> { this.setState(state =>({ count: State.count + 1}),()=>{console.log('test3-----setState callback count: ',this.state.count); } render() {return (<div> <h1> {this.state.count}</h1> <button onClick={this.test1}> test1 </button><br /> </button onClick={this.test2}> test2 </button><br /> <button onClick={this.test3}> </button><br /> </div>)}} reactdom.render (<App />, document.getelementbyid ('root')); </script> </body>Copy the code

Synchronization and asynchrony of setState

Inside setState(), a “transaction” is used to update the state asynchronously

synchronous

Timers, DOM event listening callbacks, Promises

asynchronous

Among the react controlled callbacks: lifecycle hooks, callbacks listened to by react events

How to handle asynchronous setState() calls multiple times?

Note: asynchronous case

  • SetState ({}): Merge to update the state once, only call the render() update interface once – the state update and the interface update are merged
  • SetState (fn): Updates the state multiple times, but only calls the Render update interface once, —- the status update is not merged but the interface update is merged
  • SetState ({}) object and **setState(fn)** function, state update is not merged, but interface update merged

Get asynchronously updated status data

In the callback function of setState()

case

  <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/[email protected]/babel.js"></script>
  <div id="root"></div>
  <script type="text/babel">
    
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count:0}}/** * React events listen on related callbacks: -setstate () is the */ that updates the state asynchronously 
      test1 = (a)= > {
        console.log('setSate before callback function --react event listens for callback '.this.state.count);        
        this.setState(state= >({
          count:state.count+1
        }))  
        console.log('After the setSate callback function --react event listens for the callback'.this.state.count);
      }
      /** * react Lifecycle hooks: -setState () is the */ that updates the state asynchronously 
      componentDidMount() {
        console.log('Before the setSate callback function -- Lifecycle hook'.this.state.count);        
        this.setState(state= >({
          count:state.count+1
        }))  
        console.log('After the setSate callback -- lifecycle hook'.this.state.count); 
      }
      // Sync (timer, DOM event listener callback, Promise)

      test2 = (a)= > {
        setTimeout((a)= > {
          console.log('Before setSate callback - timer'.this.state.count);        
          this.setState(state= >({
            count:state.count+1
          }))  
          console.log('After the setSate callback - timer'.this.state.count); 
        }, 0);
      }
      test4 = (a)= > {
        const btn4 = this.refs.btn4;
        btn4.onclick = (a)= > {
          console.log('Before the setSate callback -- native DOM'.this.state.count);        
          this.setState(state= >({
            count:state.count+1
          }))  
          console.log('After the setSate callback -- native DOM'.this.state.count); 
        }
      }
      test3 = (a)= > {
        Promise.resolve().then(res= > {
          console.log('Before the setSate callback --Promise'.this.state.count);        
          this.setState(state= >({
            count:state.count+1
          }))  
          console.log('After the setSate callback --Promise'.this.state.count); 
        })
      }
      test5 = (a)= > {
        console.log('setState function mode -1 -- before call '.this.state.count);
        this.setState(state= > ({
          count: state.count+1
        }))
        console.log('setState function mode -1 -- after call '.this.state.count);
        this.setState(state= > ({
          count: state.count+1
        }))
        console.log('setState function mode - 2 -- after call '.this.state.count);
      }
      test6 = (a)= > {
        console.log('setState object mode - 1 -- before call '.this.state.count);
        this.setState({count:this.state.count+1});
        console.log('setState object mode -1 -- after call '.this.state.count);
        this.setState({count:this.state.count+1});
        console.log('setState object mode - 2 -- after call '.this.state.count);
      }
      test7 = (a)= > {
        console.log('setState object mode - 1 -- before call '.this.state.count);
        this.setState({count:this.state.count+1});
        console.log('setState object mode -1 -- after call '.this.state.count);
        this.setState(state= > ({
          count: state+1
        }));
        console.log('setState function mode -1 -- after call '.this.state.count);
      }

      render() {
        return (
          <div>
            <h1>A component: {this.state.count}</h1>
            <button onClick={this.test1}>Test 1</button><br />
            <button onClick={this.test2}>Test 2</button><br />  
            <button onClick={this.test3}>Promise</button><br />   
            <button ref="btn4" onClick={this.test4}>The native DOM</button><br />                
            <button onClick={this.test5}>SetState is called multiple times - in a functional manner</button><br />   
            <button onClick={this.test6}>SetState is called multiple times in object mode</button><br />   
            <button onClick={this.test7}>SetState is called multiple times - object and function</button><br />    
          </div>
        )
      }
    }
    ReactDOM.render(<App />,document.getElementById('root'));
  </script>
Copy the code

SetState () common interview questions

If everything above is understood, the following is easy. 🙂

  <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/[email protected]/babel.js"></script>
  <div id="root"></div>
  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          count:0}}/** * Promise compared to a timer, a Promise executes setState() once, causing data to change and triggering a render update */ 

      componentDidMount() {
        this.setState({count:this.state.count+1});
        this.setState({count:this.state.count+1});
        console.log('1 --'.this.state.count); // 2 --> 0

        this.setState(state= > ({
          count: state.count+1
        }))
        this.setState(state= > ({
          count: state.count+1
        }))
        console.log('2 -- -- -- -- --.this.state.count); // 3 --> 0
        
        setTimeout((a)= > {
          this.setState({count:this.state.count+1});
          console.log('timeout-1'.this.state.count); // 8 ---> 6
          this.setState({count:this.state.count+1});
          console.log('timeout-2'.this.state.count); // 10 ---> 7
        }, 0);

        Promise.resolve().then(value= >{
          this.setState({count:this.state.count+1});
          console.log('promise-1'.this.state.count); / / 5 - > 4
          this.setState({count:this.state.count+1});
          console.log('promise-2'.this.state.count); / / 7 - > 5
        })

      }
     
      render() {
        const count = this.state.count;
        console.log('render',count); / / 1-0, 4 - > 3, 6 - > 4, 9 - > 6, 11 - > 7
        return (
          <div>
            <h1>A component: {this.state.count}</h1>            
          </div>
        )
      }
    }
    ReactDOM.render(<App />,document.getElementById('root'));
  </script>
Copy the code