SetState () two ways to update the state
-
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
-
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