根据我在react
版本16(当前)及以下版本中的了解,setState
调用是成批的IFF,它们是在组件生命周期事件或事件处理程序中进行的。否则,为了进行批量呼叫,可以使用ReactDOM.unstable_batchedUpdates
中的opt。
如果事件处理程序是async
函数,则浏览器将触发该事件处理程序,但是将返回一个promise,因此,实际的事件处理程序Promise
回调将直到运行接下来的微任务在事件循环中被拾取。换句话说,setState
更新实际上不会在立即事件处理程序中发生。
这是否意味着如果我们要在事件处理程序中分批ReactDOM.unstable_batchedUpdates
更新,就需要选择加入setState
?
答案 0 :(得分:1)
以下调用将由React进行批量处理,并将导致一次重新渲染。
const onClick = (e) => {
setHeader('Some Header');
setTitle('Some Tooltip');
};
如果没有ReactDOM.unstable_batchedUpdates
,React会进行2次sync
调用来重新渲染组件。现在,它将使用此API进行一次重新渲染。
const onClick = (e) => {
axios.get('someurl').then(response => {
ReactDOM.unstable_batchedUpdates(() => {
setHeader('Some Header');
setTitle('Some Tooltip');
});
});
};
附加说明:
更新
基于OP注释,以下是JavaScript中异步等待的版本。
const onClick = async e => {
setState(1);
setState(2);
await apiCall();
ReactDOM.unstable_batchedUpdates(() => {
setState(3);
setState(4);
});
}
以上代码将触发重新渲染两次。一次更新1/2,另一个更新3/4。
答案 1 :(得分:0)
经过研究,我相信答案是async
事件处理程序的 initial 部分(最终转换为返回的Promise
的执行函数)幕后)将批处理setState
个更新,但在进行任何await
调用后都不会更新。
这是因为async
函数主体中的所有内容,在第一个await
之前的中,都转换为执行程序函数,该函数在事件的浏览器事件处理程序中执行,但是之后的所有内容最终都变成了初始执行程序函数的链式Promise
回调,并且这些链式回调在微任务队列上执行。
这是因为async () => {}
被翻译成类似return new Promise().then()
的东西,其中每个await
都是在const onClick = async e => {
// 1 and 2 will be batched
setState(1)
setState(2)
await apiCall()
// 3 and 4 will not be batched
setState(3)
setState(4)
}
语句之后为代码创建的回调。
P2_CLIENT_ID