setState可以說是React中使用頻率最高的一個(gè)函數(shù)了,我們都知道芒炼,React是通過管理狀態(tài)來實(shí)現(xiàn)對(duì)組件的管理的,當(dāng)this.setState()被調(diào)用的時(shí)候,React會(huì)重新調(diào)用render方法來重新渲染UI
但實(shí)際使用的時(shí)候觅丰,我們會(huì)發(fā)現(xiàn),有時(shí)候我們setState之后妨退,并沒有立刻生效妇萄,例如我們看一下以下的示例代碼
class Test extends Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
this.setState({count: this.state.count + 1});
console.log(this.state.count); // 輸出0
this.setState({count: this.state.count + 1});
console.log(this.state.count); // 輸出0
setTimeout(() => {
this.setState({count: this.state.count + 1});
console.log(this.state.count); // 輸出2
this.setState({count: this.state.count + 1});
console.log(this.state.count); // 輸出3
}, 0);
}
render() {
return <div> test </div>;
}
}
開發(fā)過程中我們會(huì)發(fā)現(xiàn),在componentDidMount方法中咬荷,我們調(diào)用setState之后state的值并沒有立即改變冠句,但如果我們?cè)趕etTimeOut里面調(diào)用,我們卻能立刻就能獲得更新幸乒,原因就在于react中的使用了基于事務(wù)(傳送門懦底,關(guān)于事務(wù)原理的解析)的異步更新機(jī)制,但對(duì)于這個(gè)異步的理解罕扎,又跟ajax的異步有所不同聚唐,因?yàn)楫吘箁eact是一個(gè)js框架,所有的操作都是單線程的腔召,所有的操作杆查,都得按順序來,那么它具體是怎么實(shí)現(xiàn)的呢臀蛛?
我們都知道亲桦,對(duì)于dom的操作對(duì)性能的損耗是非常嚴(yán)重的,所以react為了提高整體的渲染性能浊仆,會(huì)將一次渲染周期中的state進(jìn)行合并客峭,在這個(gè)渲染周期中你對(duì)所有setState的所有調(diào)用都會(huì)被合并起來之后,再一次性的渲染氧卧,這樣可以避免頻繁的調(diào)用setState導(dǎo)致頻繁的操作dom桃笙,提高渲染性能。具體的實(shí)現(xiàn)方面沙绝,可以簡單的理解為react中存在一個(gè)狀態(tài)變量isBatchingUpdates搏明,當(dāng)處于渲染周期開始時(shí)鼠锈,這個(gè)變量會(huì)被設(shè)置成true,渲染周期結(jié)束時(shí)星著,會(huì)被設(shè)置成false购笆,react會(huì)根據(jù)這個(gè)狀態(tài)變量,當(dāng)出在渲染周期中時(shí)虚循,僅僅只是將當(dāng)前的改變緩存起來同欠,等到渲染周期結(jié)束時(shí),再一次性的全部render,横缔,具體的流程可以參照下面的流程圖
現(xiàn)在铺遂,我們回到最開始的問題,為什么一開始在componentDidMount中直接執(zhí)行setState會(huì)無法立刻得到更新呢茎刚,原因就在于襟锐,我們?cè)赾omponentDidMount中其實(shí)處于首次渲染的事務(wù)當(dāng)中,這次事務(wù)的渲染尚未完成膛锭,而首次渲染的時(shí)候會(huì)將isBatchingUpdates設(shè)置為true粮坞,這是我們?cè)赾omponentDidMount中調(diào)用setState,react會(huì)發(fā)現(xiàn)當(dāng)前事務(wù)尚未完成初狰,只會(huì)直接將修改后的state放入到dirtyComponents中莫杈,等待最終渲染周期完成時(shí),將所有的state進(jìn)行合并奢入,一次性render筝闹。而當(dāng)我們放在setTimeOut里面的時(shí)候,setTimeOut會(huì)將操作放到執(zhí)行隊(duì)列的最后方俊马,也就是說會(huì)等待渲染周期結(jié)束之后再進(jìn)行setState丁存,這個(gè)時(shí)候狀態(tài)變量已經(jīng)被重置回來了,所以此時(shí)我們的每一次setState都會(huì)立刻生效
那么柴我,問題來了解寝,當(dāng)我們?cè)阡秩局芷谥袌?zhí)行了setState之后,我們要如何獲取到最新的state的值呢艘儒,setTimeOut是一個(gè)方案聋伦,但是不太優(yōu)雅,有沒有其他方法呢界睁,我們注意到觉增,setState提供了一個(gè)回調(diào)函數(shù),我們只需要在回調(diào)里面獲取更新后的state即可翻斟,像這樣
componentDidMount() {
this.setState({count: this.state.count + 1},()=>{
console.log(this.state.count);//該是啥就是是啥
}));
}
————————————————
原文鏈接:https://blog.csdn.net/handsomexiaominge/article/details/86348235