kangyana / daily-question

When your heart is set on something, you get closer to your goal with each passing day.
https://www.webpack.top
MIT License
3 stars 0 forks source link

【Q063】setState 批更新 #63

Open kangyana opened 2 years ago

kangyana commented 2 years ago

1. setState 同步更新还是异步更新?

React18 以前的版本

react 事件中,setState 是异步更新的。 但是在 setTimeoutaddEventListener 添加的原生事件中,setState 则是同步的。

// Legacy同步模式

const container = document.getElementById('root');
ReactDOM.render(<App />, container);

React18 以后

setState 的更新统一是异步的。

// Concurrent异步模式,在这个模式下,任何情况下setState都是异步更新的。目前createRoot方法还在实验中

const container = document.getElementById('root');
ReactDOM.createRoot(container).render(<App />)

2. setState 批更新

在 React 18 之前,如果在回调函数的异步调用中,执行 setState,由于丢失上下文,无法做合并处理。 所以每次 setState 调用都会触发一次 重新渲染

function handleClick() {
    // React 18 之前的版本
    (/*...*/).then(() => {
        setCount(c => c + 1); // 立刻重新渲染
        setShow(show => !show); // 立刻重新渲染
    });
}

React 18中,任何情况下都可以合并渲染! 如果仍然希望setState之后立即重新渲染,只需要使用 flushSync 包裹。

function handleClick() {
    // React 18
    fecth(/*...*/).then(() => {
        ReactDOM.flushSync(() => {
            setCount(c => c + 1); // 立刻重新渲染
            setFlag(f => !f);
        })
    })
}