react动态增加state_问一个react更新State的问题?

这个问题确实像其他回答评价的那样,“老生常谈”了。

但是有两点我不是很理解:为什么其他回答都是上来就说“React setState 更新是异步的”?(错误的误导)

为什么在很多答主本身都并没有完全理解这个问题的情况下,就“教育”“嘲讽”题主自己查资料、解决问题?

先说第二点,如果所有人都具备亲自手动查资料解决问题的能力,那么社区上是不是就会少太多“愚蠢”的问题和针对幼稚问题的详尽答案。

作为开发者,我们一定要具备自学自研的能力。同时,时刻都要 be humble,“冷嘲热讽他人提问,数落他人不会自己查问题解决”不是很好的表现。

“有问题,尽管问”才会有高质量的回答,才会有其他人“自行查询”解决的前提。

再来说第一点,回到问题的本身。我企图从 React 官方找到问题的答案:setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState()a potential pitfall.

Voilà, 准确的用词是batch later 或者 defer, 这种表达和我们传统上所谓的“异步”不尽相同。另外,人家用词明显是 may,因此我们知道这种所谓的“延迟更新”并不 cover 100% cases。换句话说,某些情况下,它也是能够马上或者“同步”完成更新的。

那么,怎么就像其他答主所说的那样,一定就是异步更新了呢?There is no guarantee that this.state will be immediately updated, so

accessing this.state after calling this method may return the old value.

首先,不保证马上更新是真的,比如我们试验这样的代码:

function incrementMultiple() {

this.setState({count: this.state.count + 1});

this.setState({count: this.state.count + 1});

this.setState({count: this.state.count + 1});

}

直观上来看,当上面的 incrementMultiple 函数被调用时,组件状态的 count 值被增加了3次,每次增加1,那最后 count 被增加了3。但是,实际上的结果只给 state 增加了1。

事实上,setState 方法与包含在其中的执行是一个很复杂的过程,从 React 最初的版本到现在,也有无数次的修改。它的工作除了要更动 this.state 之外,还要负责触发重新渲染,这里面要经过 React 核心 diff 算法,最终才能决定是否要进行重渲染,以及如何渲染。而且为了批次与效能的理由,多个 setState 呼叫有可能在执行过程中还需要被合并,所以它被设计以延时的来进行执行是相当合理的。图片来源于网络,侵删

但是,你再试试:

componentDidMount() {

document.querySelector('#btn-raw').addEventListener('click', this.onClick);

}

onClick() {

this.setState({count: this.state.count + 1});

console.log('# this.state', this.state);

}

// ......render() {

console.log('#enter render');

return (

{this.state.count}

Increment Raw

)

}

你会发现,控制台又打印出了准确的 count 值,进行了同步更新!

深入源码你会发现:在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中回头再说,而 isBatchingUpdates 默认是 false,也就表示 setState 会同步更新 this.state,但是,有一个函数 batchedUpdates,这个函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,造成的后果,就是由 React 控制的事件处理过程 setState 不会同步更新 this.state。

划重点时间:

由 React 控制的事件处理过程 setState 不会同步更新 this.state!

也就是说,

在 React 控制之外的情况, setState 会同步更新 this.state!

但大部份的使用情况下,我们都是使用了 React 库中的表单组件,例如 select、input、button 等等,它们都是 React 库中人造的组件与事件,是处于 React 库的控制之下,比如组件原色 onClick 都是经过 React 包装。在这个情况下,setState 就会以异步的方式执行。

所以一般来说,其他答主会误认为 setState 就是异步执行。

实际上,绕过 React 通过 JavaScript 原生 addEventListener 直接添加的事件处理函数,还有使用 setTimeout/setInterval 等 React 无法掌控的 APIs情况下,就会出现同步更新 state 的情况。

曾经有人突发奇想,把 setState 函数 promise 风格化,全部异步执行,并返回一个 promise。这是很有意思的,并给 React 提了 PR,里边的故事可以参考我写的文章: 从setState promise化的探讨 体会React团队设计思想

其实,还有很多可以深入的细节。我先吃饭去了,回来有时间可以更多跟大家讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值