在同一个方法中屡次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