setState
的执行是一个 '异步'
的过程,为何会将这两个字用引号代替,确定其中有必定的道理,下面对 setState
进行分析javascript
React 源码,setState
中传入两个参数 partialState, callback
:java
partialState
在字面意思理解应该是部分状态,注释说明是这样的 Next partial state or function to produce next partial state to be merged with current state.
,大概翻译是 下一个部分状态或函数,以产生下一个要与当前状态合并的部分状态。
。实际上,在项目中 this.setState({})
更新指定 state
时,其余的 state
与当前更新的 state
作了合并。callback
回调函数,意指状态更新后的回调,在该函数中获取最新的 state
。setState
处理过程首先调用了 invariant()
, 其次调用了 this.updater.enqueueSetState()
react
/packages/shared/invariant.js
, 这个方法就是判断 partialState
的类型是否正确,抛出错误,附上源码:git
可是在 V16.7.0版本以前 invariant
抛出的是不一样类型的错误:github
/packages/react-dom/src/server/ReactPartialRenderer.js
,把即将更新的 state
push 到了 queue
中,在 new Component
时,将 updater
传进去,附上源码:antd
queue
应该是 React
提高性能的关键。由于并非每次调用 setState
, React
都会立马更新,而是每次调用 setState
, React
只是将其 push 到了待更新的 queue
中,附上源码:dom
/packages/react-reconciler/src/ReactFiberClassComponent.js
中的 enqueueSetState
;异步
/packages/react-reconciler/src/ReactUpdateQueue.js
中的 enqueueUpdate
;函数
import React from 'react'; import {Button} from 'antd'; class SetState extends React.Component { state = { val: 0 } componentDidMount() { this.setState({ val: this.state.val + 1 }) console.log('钩子函数:', this.state.val) // 输出的仍是更新前的值 --> 0 } increment = () => { this.setState({ val: this.state.val + 1 }) console.log('合成方法:', this.state.val) // 输出的是更新前的val --> 1 } render() { return ( <Button type="primary" onClick={this.increment}> 钩子函数及合成方法 --> {`Counter is: ${this.state.val}`} </Button> ) } } export default SetState;
import React from 'react'; import {Button} from 'antd'; class SetState extends React.Component { constructor(props) { super(props); this.state = { val: 0 } } componentDidMount() { document.body.addEventListener('click', this.changeValue, false) } changeValue = () => { this.setState({ val: this.state.val + 1 }) console.log('原生js事件:', this.state.val) // 输出的是更新后的值 --> 1 } render() { return ( <Button type="peimary"> 原生js事件 --> {`Counter is: ${this.state.val}`} </Button> ) } } export default SetState;
import React from 'react'; import {Button} from 'antd'; class SetState extends React.Component { constructor(props) { super(props); this.state = { val: 0 } } componentDidMount() { setTimeout(_ => { console.log('定时器->1:', this.state.val) // 输出更新前的值 --> 0 this.setState({ val: this.state.val + 1 }) console.log('定时器->2:', this.state.val) // 输出更新后的值 --> 1 }, 0); console.log('钩子函数:', this.state.val) // 输出更新前的值 --> 0 } render() { return ( <Button type="primary"> setTimeout 定时器 --> {`Counter is: ${this.state.val}`} </Button> ) } } export default SetState;
import React from 'react'; import {Button} from 'antd'; class SetState extends React.Component { constructor(props) { super(props); this.state = { val: 0 } } batchUpdates = () => { this.setState({ val: this.state.val + 1 }) this.setState({ val: this.state.val + 1 }) this.setState({ val: this.state.val + 1 }) } render() { return ( <Button type="primary" onClick={this.batchUpdates}> 批量更新 --> {`Counter is: ${this.state.val}`} </Button> ) } } export default SetState;
import React from 'react'; import {Button} from 'antd'; class SetState extends React.Component { constructor(props) { super(props); this.state = { val: 0 } } // 钩子函数中的 setState 没法立马拿到更新后的值; // setState 批量更新的策略; // setTimmout 中 setState 是能够同步拿到更新结果 componentDidMount() { this.setState({ val: this.state.val + 1 }) console.log('第一步->钩子函数:', this.state.val); // 0 this.setState({ val: this.state.val + 1 }) console.log('第二步->钩子函数:', this.state.val); // 0 setTimeout(_ => { this.setState({ val: this.state.val + 1 }) console.log('第三步->定时器:', this.state.val); // 2 this.setState({ val: this.state.val + 1 }) console.log('第四步->定时器:', this.state.val); // 3 }, 0) } render() { return ( <Button type="primary"> 钩子函数及 setTimmout 定时器 --> {`Counter is: ${this.state.val}`} </Button> ) } } export default SetState;
若是但愿在 setState
时就能获取到最新值,能够在 setState
的回调函数中获取最新结果源码分析
this.setState( { data: newData }, () => { console.log('回调函数中获取:', me.state.data) } );
setState
所谓的 '异步',实际上只在合成事件一辈子命周期函数中存在,在原生js时间与定时器中任然是同步变化的, setState
中还作了批量更新的优化。若是但愿在 this.setState({})
后及时获取到最新 state
,能够在其回调函数中获取。