更新状态 setState
react 类式组件更新页面可以通过组件实例访问 this.setState(stateChange, callback)
方法。
setState
函数,可以接收两个参数,作用:更新状态,重新调用当前组件的 render 渲染- 第一个参数:为对象或者函数,在框架底层将此对象本身或者函数调用后的返回值与当前状态,进行类似
Object.assign()
的合并操作。// 对象 this.setState({ counter: this.state.counter + this.props.increment, }) // 函数 this.setState((preState, props) => ({ counter: preState.counter + props.increment }))
- 第二个参数:为回调函数,在状态数据合并操作完毕后,调用组件的 render 渲染函数之前,才执行第二个参数回调。
render() { let { count } = this.state return <div> <button onClick={() => { this.setState({ count: count + 1 }, () => { console.log('改变之前 count', count); console.log('改变之后 count', this.state.count); }) }}>点我加1</button> 当前计数器为{count} </div> }
- 第一个参数:为对象或者函数,在框架底层将此对象本身或者函数调用后的返回值与当前状态,进行类似
setState()
这一句调用代码本身是同步执行,但是【合并操作】与 【调用 render 渲染函数】这两个底层行为都是异步执行的(微任务)。所以要小心,在同步执行的代码中取值行为,如下代码,两次取值之后,合并操作与重新渲染组件才会执行,所以两次取值都是相同的。state = { count: 0 } // ❌ 第二次调用,this.state.count 值与第一次调用取值是一样的,都是 0 + 1 handle = () => { this.setState({ count: this.state.count + 1 }, () => { ... }) this.setState({ count: this.state.count + 1 }, () => { ... }) } // ✅ 将 setState 的第一个参数写为函数即可收到每次更新的值 handle = () => { this.setState(preState => ({ count: preState.count + 1 }), () => { ... }) this.setState(preState => ({ count: preState.count + 1 }), () => { ... }) }
setState 执行流程
- 当 setState 函数第一个参数为对象时:
- 执行同步代码: setState 函数调用,第一个参数对象成员取值,注册下面的 3 个异步微任务,继续执行后面的同步代码
- 清空(执行)当前宏任务中的微任务:
- 执行合并操作任务,将第一个参数对象与当前 state 对象合并(状态数据更新了)
- 执行 setState 的第二个参数回调
- 执行当前组件的 render 函数(视图更新了)
- 当 setState 函数第一个参数为函数时:
- 执行同步代码: setState 函数调用,第一个参数函数定义,注册下面的 4 个异步微任务,继续执行后面的同步代码
- 清空(执行)当前宏任务中的微任务:
- 执行第一个参数函数,拿到返回值对象,将对象成员取值
- 执行合并操作任务,将返回值对象与当前 state 对象合并(状态数据更新了)
- 执行 setState 的第二个参数回调
- 执行当前组件的 render 函数(视图更新了)
多次调用合并渲染
当多次调用 setState 函数时,react 做了性能优化。
-
同步代码环境中调用 setState:在正常的 react 的事件流里,一个类式组件多次执行 setState 或者函数组件某个 useState 中的 setXXX 多次执行,只会调用一次重新渲染 render,称为合并渲染
-
异步代码环境中调用 setState:在 setTimeout,Promise.then 等异步事件中,多次执行 setState 和 useState 中的 setXXX,每次执行都会调用 render 渲染函数
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!