Handle Class Component setState edge-case with ReactDOM.flushSync

Michael Chan
InstructorMichael Chan
Share this video with your friends

Social Share Links

Send Tweet
Published 3 years ago
Updated 3 years ago

React 17 had an edge-case that meant that this.state could show partial state changes. This was never intended and has been patched in React 18. In cases where you need that same behavior, ReactDOM.flushSync to achieve the same result. While it's an available option, it is not recommended.

Instructor: [0:00] React 17 had a pretty strange edge case when using class components. In this class component, we have two pieces of state, a count() and isOdd(), and we want them to update together, even though we're updating state twice.

[0:13] These are batched whether or not they're in the handleClick() directly, or a callback is called later on as a result of setTimeout() or a promise. Running this in a React 17 environment, we see something strange happen, where these console log statements can log partial states after these updates. Let's check it out.

[0:36] We see count() incremented, but isOdd() is false for the first console.log. Then, for the second, we see that state updated as well. This behavior changes as soon as we enable React 18 through the new createRoot API. Let's try this again. Here, we see that both log the original state before the update.

[0:58] While it's not recommended, we can enable the behavior that we had before with ReactDOM flushSync. We wrap this update in a function, and we can leave our console.log exactly where it was right here. Let's try that again. Here, we see the first partial updates, so that part is working.

[1:17] In order to get the same exact behavior, we need to wrap both of these in this flushSync. Any console log is going to need this flushSync wrapped around it. Let's Save that again, Refresh, and now, we see the behavior as it was before. This is not recommended, but it is an escape hatch should you need it.