关于setState
官网说明 https://zh-hans.reactjs.org/docs/faq-state.html#what-does-setstate-do
setstate在原生事件,setTimeout,setInterval,promise等异步操作中,state会同步更新文档提到setState是异步的https://zh-hans.reactjs.org/docs/faq-state.html#when-is-setstate-asynchronous
那再了解一下setState是否能同步执行,答案是能
1、原生事件同步import React, {Component} from 'react';
class Test4 extends Component {
state = {
n1: 0,
n2: 0
}
onTab1(){
this.setState({
n1: this.state.n1 + 1
})
console.log("第一个n1",this.state.n1)
this.setState({
n1: this.state.n1 + 1
})
console.log("第二个n1",this.state.n1)
}
onTab2(){
this.setState({
n2: this.state.n2 + 1
})
console.log("第一个n2",this.state.n2)
this.setState({
n2: this.state.n2 + 1
})
console.log("第二个n2",this.state.n2)
}
componentDidMount() {
document.getElementById("btn").addEventListener('click', this.onTab2.bind(this), false);
}
render() {
return (
n1:{this.state.n1}
n2:{this.state.n2}
合成事件测试同步
原生事件测试同步
);
}
}
export default Test4;
onClick是react的合成事件,setState表现为异步。 addEventListener为原生事件,表现为同步
2、setTimeout同步import React, {Component} from 'react';
class Test4 extends Component {
state = {
n1: 0,
n2: 0
}
onTab1(){
this.setState({
n1: this.state.n1 + 1
})
console.log("第一个n1",this.state.n1)
this.setState({
n1: this.state.n1 + 1
})
console.log("第二个n1",this.state.n1)
}
onTab2(){
setTimeout(()=>{
this.setState({
n2: this.state.n2 + 1
})
console.log("第二个n2",this.state.n2)
this.setState({
n2: this.state.n2 + 1
})
console.log("第二个n2",this.state.n2)
},500)
}
render() {
return (
n1:{this.state.n1}
n2:{this.state.n2}
合成事件测试同步
setTimeout测试同步
);
}
}
export default Test4;
import React, {Component} from 'react';
class Test4 extends Component {
state = {
n1: 0,
n2: 0
}
onTab1(){
this.setState({
n1: this.state.n1 + 1
})
console.log("第一个n1",this.state.n1)
this.setState({
n1: this.state.n1 + 1
})
console.log("第二个n1",this.state.n1)
}
onTab2(){
new Promise(((resolve, reject) => {
resolve()
})).then(()=>{
this.setState({
n2: this.state.n2 + 1
})
console.log("第二个n2",this.state.n2)
this.setState({
n2: this.state.n2 + 1
})
console.log("第二个n2",this.state.n2)
})
}
render() {
return (
n1:{this.state.n1}
n2:{this.state.n2}
合成事件测试同步
Promise测试同步
);
}
}
export default Test4;
setstate方法
ReactComponent.prototype.setState = function (partialState, callback) {
// 将setState事务放进队列中
this.updater.enqueueSetState(this, partialState);
if (callback) {
this.updater.enqueueCallback(this, callback, 'setState');
}
};
enqueueSetState: function (publicInstance, partialState) {
// 获取当前组件的instance
var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, 'setState');
// 将要更新的state放入一个数组里
var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);
queue.push(partialState);
// 将要更新的component instance也放在一个队列里
enqueueUpdate(internalInstance);
}
function enqueueUpdate(component) {
// 如果没有处于批量创建/更新组件的阶段,则处理update state事务
if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component);
return;
}
// 如果正处于批量创建/更新组件的过程,将当前的组件放在dirtyComponents数组中
dirtyComponents.push(component);
}
var ReactDefaultBatchingStrategy = {
// 用于标记当前是否出于批量更新
isBatchingUpdates: false,
// 当调用这个方法时,正式开始批量更新
batchedUpdates: function (callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;
ReactDefaultBatchingStrategy.isBatchingUpdates = true;
// 如果当前事务正在更新过程在中,则调用callback,既enqueueUpdate
if (alreadyBatchingUpdates) {
return callback(a, b, c, d, e);
} else {
// 否则执行更新事务
return transaction.perform(callback, null, a, b, c, d, e);
}
}
};
batchedUpdates 发起 transaction.perform() 事务 这个事务流程中的 anyMethod 是 runBatchedUpdates ,即更新组件状态并走一遍组件生命周期,在 componentWillMount 时将 A 状态队列里累积的状态都依次处理了。 wrapper close,循环遍历 dirtyComponents 并执行 transaction.perform(runBatchedUpdates, null, transaction); 于是 A 就被捡起来开始走事务流程直到 dirtyComponents 里最后一个组件跑完流程,组件都被统一更新了一遍。
以上源码内容分析来自https://www.jianshu.com/p/89a04c132270
再函数式组件中,都是异步import React, {useState} from "react";
export default function Fn() {
const [num1, setNum1] = useState(0);
const [num2, setNum2] = useState(0);
const onTab1 = () => {
setNum1(num1 + 1)
console.log("第一个num1", num1)
setNum1(num1 + 1)
console.log("第二个num1", num1)
}
const onTab2 = () => {
setTimeout(()=>{
setNum2(num2 + 1)
console.log("第一个num2", num1)
setNum2(num2 + 1)
console.log("第二个num2", num1)
},500)
}
return (
num1:{num1}
num2:{num2}
默认异步
setTimeout也是异步
)
}
import React, {useState} from "react";
export default function Fn() {
const [num1, setNum1] = useState(0);
const [num2, setNum2] = useState(0);
const onTab1 = () => {
setNum1(num1 + 1)
console.log("第一个num1", num1)
setNum1(num1 + 1)
console.log("第二个num1", num1)
}
const onTab2 = () => {
setNum2(num2=>num2 + 1)
console.log("第一个num2", num2)
setNum2(num2 =>num2 + 1)
console.log("第二个num2", num2)
}
return (
num1:{num1}
num2:{num2}
默认异步
state同步,执行顺序不同步
)
}
注意:class组件和hooks都可以这样