对于类组件,this.setState如果在事件处理程序内部,则调用批处理。但是,如果在事件处理程序外部并使用useState钩子来更新状态,会发生什么?
this.setState
useState
function Component() { const [a, setA] = useState('a'); const [b, setB] = useState('b'); function handleClick() { Promise.resolve().then(() => { setA('aa'); setB('bb'); }); } return <button onClick={handleClick}>{a}-{b}</button> }
它会立即渲染aa - bb吗?还是会aa - b然后aa - bb呢?
aa - bb
aa - b
TL; DR –如果状态更改是异步触发的(例如,包装在Promise中),则不会进行批处理;如果直接触发它们,将对其进行批处理。
我已经设置了一个沙箱来尝试一下:https : //codesandbox.io/s/402pn5l989
import React, { Fragment, useState } from 'react'; import ReactDOM from 'react-dom'; import './styles.css'; function Component() { const [a, setA] = useState('a'); const [b, setB] = useState('b'); console.log('a', a); console.log('b', b); function handleClickWithPromise() { Promise.resolve().then(() => { setA('aa'); setB('bb'); }); } function handleClickWithoutPromise() { setA('aa'); setB('bb'); } return ( <Fragment> <button onClick={handleClickWithPromise}> {a}-{b} with promise </button> <button onClick={handleClickWithoutPromise}> {a}-{b} without promise </button> </Fragment> ); } function App() { return <Component />; } const rootElement = document.getElementById('root'); ReactDOM.render(<App />, rootElement);
我做了两个按钮,一个触发状态更改,就像您的代码示例一样,包装在一个promise中,另一个触发状态更改。
如果您查看控制台,则在单击“ promise”按钮时,它将首先显示a aa和b b,然后显示a aa和b bb。
a aa
b b
b bb
因此答案是否定的,在这种情况下,它不会立即渲染aa - bb,每次状态更改都会触发一个新的渲染,没有批处理。
但是,当您点击按钮“不承诺”,控制台将显示a aa和b bb马上。
因此,在这种情况下,React会批处理状态更改,并为两者一起进行一个渲染。