赞
踩
setState是‘最熟悉的陌生人’,当你入门React的时候,接触的第一波API里一定有setState-----数据驱动视图。当你项目的数据流乱作一团的时候,始作俑者也往往是setState----工作机制太复杂,文档又不说清楚。
setState 的工作机制渐渐与 React 调和算法并驾齐驱,成了 React 核心原理中区分度最高的知识模块之一。
“神奇时刻”到底何时发生?
state到底是在哪个环节发生了变化呢?
所谓的“恰恰好”又如何界定呢?
关于setState的问题,由下面一段代码说起:
给出一个这样的 App 组件,在它的内部会有如下代码所示的几个不同的 setState 操作:
- import React, { Component } from 'react';
-
- export default class App extends Component {
- state = {
- count: 0
- };
-
- handleIncrement = () => {
- console.log('increment setState前的count', this.state.count);
- this.setState({
- count: this.state.count + 1
- });
- console.log('increment setState后的count', this.state.count);
- };
-
- handleTriple = () => {
- console.log('triple setState前的count', this.state.count);
- this.setState({
- count: this.state.count + 1
- });
- this.setState({
- count: this.state.count + 1
- });
- this.setState({
- count: this.state.count + 1
- });
- console.log('triple setState后的count', this.state.count);
- };
-
- handleReduce = () => {
- setTimeout(() => {
- console.log('reduce setState前的count', this.state.count);
- this.setState({
- count: this.state.count - 1
- });
- console.log('reduce setState后的count', this.state.count);
- }, 0);
- };
-
- render() {
- return (
- <div>
- <div>{this.state.count}</div>
- <button onClick={this.handleIncrement}>点我增加</button>
- <button onClick={this.handleTriple}>点我增加三倍</button>
- <button onClick={this.handleReduce}>点我减少</button>
- </div>
- );
- }
- }
此时有个问题,若从左到右依次点击每个按钮,控制台的输出会是什么样的?
如果你是一个熟手 React 开发,那么 handleIncrement这个方法的输出结果想必难不倒你——正如许许多多的 React 入门教学所声称的那样,“setState是一个异步的方法”,这意味着当我们执行完 setState 后,state本身并不会立刻发生改变。 因此紧跟在 setState后面输出的 state值,仍然会维持在它的初始状态(0)。在同步代码执行完毕后的某个“神奇时刻”,state才会“恰恰好”地增加到 1。
但这个“神奇时刻”到底何时发生,所谓的“恰恰好”又如何界定呢?如果你对这个问题搞不太清楚,那么 triple方法的输出对你来说就会有一定的迷惑性——setState一次不好使, setState三次也没用,state 到底是在哪个环节发生了变化呢?
带着这样的困惑,你决定先抛开一切去看看 handleReduce方法里是什么光景,结果更令人大跌眼镜,reduce 方法里的 setState竟然是同步更新的!这…到底是我们初学 React时拿到了错误的基础教程,还是电脑坏了?
在setState
调用之后,都发生了哪些事情?基于截止到现在的专栏知识储备,可能会更倾向于站在生命周期的角度去思考这个问题,得出一个如下图所示的结论:
从图上我们可以看出,一个完整的更新流程,涉及了包括 re-render(重渲染) 在内的多个步骤。re-render本身涉及对 DOM 的操作,它会带来较大的性能开销。假如说“一次 setState就触发一个完整的更新流程”这个结论成立,那么每一次 setState的调用都会触发一次 re-render,我们的视图很可能没刷新几次就卡死了。这个过程如我们下面代码中的箭头流程图所示:
th
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。