From d14cbdca2445cd676526c4c52e1e106342ff7bb3 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 7 Apr 2022 15:39:12 +0100 Subject: [PATCH] Add more details on batching (#4559) * Add more details on batching * Use a generic example --- content/docs/hooks-reference.md | 8 ++++++++ content/docs/reference-react-component.md | 2 +- content/docs/reference-react-dom.md | 12 ++++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/content/docs/hooks-reference.md b/content/docs/hooks-reference.md index cd163626..28a821be 100644 --- a/content/docs/hooks-reference.md +++ b/content/docs/hooks-reference.md @@ -108,6 +108,14 @@ If you update a State Hook to the same value as the current state, React will ba Note that React may still need to render that specific component again before bailing out. That shouldn't be a concern because React won't unnecessarily go "deeper" into the tree. If you're doing expensive calculations while rendering, you can optimize them with `useMemo`. +#### Batching of state updates {#batching-of-state-updates} + +React may group several state updates into a single re-render to improve performance. Normally, this improves performance and shouldn't affect your application's behavior. + +Before React 18, only updates inside React event handlers were batched. Starting with React 18, [batching is enabled for all updates by default](/blog/2022/03/08/react-18-upgrade-guide.html#automatic-batching). Note that React makes sure that updates from several *different* user-initiated events -- for example, clicking a button twice -- are always processed separately and do not get batched. This prevents logical mistakes. + +In the rare case that you need to force the DOM update to be applied synchronously, you may wrap it in [`flushSync`](/docs/react-dom.html#flushsync). However, this can hurt performance so do this only where needed. + ### `useEffect` {#useeffect} ```js diff --git a/content/docs/reference-react-component.md b/content/docs/reference-react-component.md index a5dabb5d..487706e0 100644 --- a/content/docs/reference-react-component.md +++ b/content/docs/reference-react-component.md @@ -512,7 +512,7 @@ setState(updater, [callback]) `setState()` enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. This is the primary method you use to update the user interface in response to event handlers and server responses. -Think of `setState()` as a *request* rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. React does not guarantee that the state changes are applied immediately. +Think of `setState()` as a *request* rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass. In the rare case that you need to force the DOM update to be applied synchronously, you may wrap it in [`flushSync`](/docs/react-dom.html#flushsync), but this may hurt performance. `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. Instead, use `componentDidUpdate` or a `setState` callback (`setState(updater, callback)`), either of which are guaranteed to fire after the update has been applied. If you need to set the state based on the previous state, read about the `updater` argument below. diff --git a/content/docs/reference-react-dom.md b/content/docs/reference-react-dom.md index f6dfe953..bc6d8df5 100644 --- a/content/docs/reference-react-dom.md +++ b/content/docs/reference-react-dom.md @@ -62,11 +62,19 @@ Creates a portal. Portals provide a way to [render children into a DOM node that flushSync(callback) ``` -Force React to flush any updates inside the provided callback synchronously. This method is useful for being able to read the result of those updates immediately. +Force React to flush any updates inside the provided callback synchronously. This ensures that the DOM is updated immediately. + +```javascript +// Force this state update to be synchronous. +flushSync(() => { + setCount(count + 1); +}); +// By this point, DOM is updated. +``` > Note: > -> `flushSync` can have a significant impact on performance. Use sparingly. +> `flushSync` can significantly hurt performance. Use sparingly. > > `flushSync` may force pending Suspense boundaries to show their `fallback` state. >