在同一個方法中屢次setState是會被合併的,而且對相同屬性的設置只保留最後一次的設置;react
import React from 'react'; export class Test extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentWillMount() { let me = this; me.setState({ count: me.state.count + 2 }); me.setState({ count: me.state.count + 1 }); } componentDidMount() { let me = this; me.setState({ count: me.state.count + 2 }); me.setState({ count: me.state.count + 1 }); } onClick() { let me = this; me.setState({ count: me.state.count + 1 }); me.setState({ count: me.state.count + 1 }); } render() { console.log(this.state.count); console.log('1111111111111111111111111111111111111111111'); return ( <div> <h1>{this.state.count}</h1> <input type="button" value="點擊我" onClick={this.onClick.bind(this)} /><br /> <br /> </div> ) } }
上述執行過程以下:ajax
willmount
中的setState
會合併成一次執行,count
只會保留最後一次的設置,前面的放棄,因此willmount
以後是1
,並非3
;而且在render
以前執行,不會引發新的render
- render以後執行didMount,setState作一樣的處理,這是
count
是2
,而且引發新的render- 點擊按鈕,
setState
作一樣處理,count
是3
,引發新的render
定時器中的setState,每次都會引發新的render,即便是同一個定時器中的屢次setStatejson
代碼更改爲以下:api
componentWillMount() { let me = this; setTimeout(() => { me.setState({ count: me.state.count + 1 }); me.setState({ count: me.state.count + 1 }); }, 0); } componentDidMount() { let me = this; setTimeout(() => { me.setState({ count: me.state.count + 1 }); me.setState({ count: me.state.count + 1 }); }, 0); } onClickTime() { let me = this; setTimeout(() => { me.setState({ count: me.state.count + 1 }); me.setState({ count: me.state.count + 1 }); }, 0); }
上述代碼,每次setState
都會引起新的render,須要深刻了解的能夠查查setState
的原理,簡單理解是定時器中的setState
沒走react
的事物機制,執行時批量更新沒被設置true
,因此每次都直接render了。
在按鈕原生事件中定義的setState
,和定時器效果同樣, 每次setState
都會引發新的render
react事件是合併的成一次render的。
componentDidMount() { this.button.addEventListener('click', this.onClick.bind(this, '原生事件'), false); } onClick(info) { console.log(info); this.setState({ count: ++count }); this.setState({ count: ++count }); } render() { console.log(this.state.count); return <div> <input type="button" ref={input => this.button = input} onClick={this.onClick.bind(this, 'React事件')} value="生成計時器" /> <div>Count:{this.state.count}</div> </div> }
點擊按鈕,先執行原生事件,再執行react事件,可是原生事件會觸發兩次render,react事件觸發一次。
上述是我對setState的理解,拋磚引玉,但願幫助你們有方向的去了解react原理機制。剛開始接觸,不少同窗想深刻了解,但可能不知道從何入手,這也是我遇到過的困擾,因此如今分享出來,但願能幫助你們少走彎路,更快的、更有準針對性的去研究學習React。promise
如下爲補充內容函數
其實在回調函數中,setState是不會觸發批量更新機制的,不管是promise,ajax,setTimeout回調等等,同時設置屢次setState,每一個setState都會單獨執行並render,由於上下文發生了變化。學習
下面是驗證codefetch
onClickBtn = () => { // const promise = new Promise((resolve, reject) => { // this.setState({ count: this.state.count + 1 }); // console.log(this.state.count); // this.setState({ count: this.state.count + 1 }); // console.log(this.state.count); // resolve(); // }); // promise.then(() => { // this.setState({ count: this.state.count + 1 }); // console.log(this.state.count); // this.setState({ count: this.state.count + 1 }); // console.log(this.state.count); // }); fetch("/api/getlist") .then(response => { return response.json(); }) .then(data => { console.log(JSON.stringify(data)); this.setState({ count: this.state.count + 1 }); console.log(this.state.count); this.setState({ count: this.state.count + 1 }); console.log(this.state.count); }); };
在寫demo時發現,雖然didMount
中的屢次setState
會被合併,符合正常的規律,可是經過調試發現,在didMount
中isBatchingUpdates
始終是false
,而事件調用觸發的setState
,isBatchingUpdates
則是true
。this