State Update Batching | Lecture 132 | React.JS 🔥
Summary
TLDRThis video script delves into the intricacies of React's state update batching process. It explains how React optimizes performance by batching multiple setState calls into a single state update, triggering only one re-render instead of multiple. The speaker illustrates this concept through code examples, highlighting the asynchronous nature of state updates and the potential for stale state before the re-render. Additionally, the script covers React 18's improved batching capabilities, extending automatic batching to situations like timeouts and promises, and mentions rare cases where disabling batching might be necessary.
Takeaways
- 🤝 React batches multiple state updates in event handlers into a single re-render for better performance.
- ⌚ Accessing the state variable immediately after calling setState will return the stale (previous) value, as the state update is asynchronous and only reflected after re-render.
- 📤 If you need to update state based on the previous state update in the same event handler, pass a callback function to setState instead of a value.
- 🆕 React 18 introduced automatic batching for state updates triggered outside React event handlers, such as timeouts, promises, and native events.
- ⚠️ In rare cases where automatic batching causes issues, you can wrap the problematic state update in ReactDOM.flushSync() to exclude it from batching.
- 🧩 Batching state updates makes sense conceptually, as it represents a single new view rather than multiple partial updates.
- ⚡ Avoiding unnecessary re-renders by batching state updates is a performance optimization provided by React out-of-the-box.
- 🔄 Before React 18, state updates triggered outside React event handlers were not batched, leading to multiple re-renders.
- 🧐 Understanding batching is important, especially when working with older React versions where it behaved differently.
- 🎥 The video provides a detailed explanation of state update batching in React, a crucial concept for optimizing performance.
Q & A
What is state batching in React?
-State batching in React refers to the mechanism where multiple state updates within the same event handler are combined into a single re-render. Instead of triggering a re-render for each individual state update, React batches these updates together and performs only one re-render.
Why does React batch state updates?
-React batches state updates for performance optimization. If multiple state updates are related and meant to represent a new view, it would be inefficient to trigger multiple re-renders for each update. Batching ensures that only one re-render occurs, which improves the application's performance.
Can you access the updated state immediately after calling the setState function?
-No, you cannot access the updated state immediately after calling the setState function. The state update is asynchronous, and the new state value is only available after the re-render cycle has completed. Attempting to access the state variable right after calling setState will still give you the previous (stale) state value.
How can you update state based on the previous state value in the same event handler?
-To update state based on the previous state value within the same event handler, you can pass a callback function to the setState function instead of a single value. The callback function receives the previous state as an argument and returns the new state based on that value.
Did React batch state updates in all situations before React 18?
-No, before React 18, state updates were only batched in event handlers triggered by browser events (e.g., click, submit). Updates triggered outside of event handlers, such as timeouts, promises, or native event handlers, were not batched automatically.
What is the behavior of state batching in React 18 and later versions?
-In React 18 and later versions, state updates are batched automatically in all situations, including timeouts, promises, and native event handlers. This improvement enhances performance by reducing unnecessary re-renders.
Is there a way to opt-out of automatic batching in React?
-Yes, in rare cases where automatic batching might cause problems, you can opt-out by wrapping the problematic state update within the ReactDOM.flushSync function. This will exclude that specific update from being batched.
Why is it important to understand state batching in React?
-Understanding state batching is crucial because it affects the way you work with state updates and can have surprising results if not accounted for. It also helps in writing more efficient and performant React applications by avoiding unnecessary re-renders.
Can state batching lead to unexpected behavior if not handled properly?
-Yes, state batching can lead to unexpected behavior if not handled properly. For example, if you try to access the state value immediately after calling setState, you might get the previous (stale) state value instead of the updated one, which could cause bugs or unintended behaviors.
How does state batching relate to the overall render lifecycle in React?
-State batching is an important part of the render lifecycle in React. It occurs during the initial triggering phase, where React collects all state updates that need to be applied. The batched updates are then processed during the render phase, and a single re-render is triggered, followed by the commit phase.
Outlines
📚 State Update Batching in React
This paragraph explains the concept of state update batching in React. It clarifies that when multiple state variables are updated within the same event handler, React batches these updates into a single state update, triggering only one re-render and commit phase. This behavior serves as a performance optimization, avoiding unnecessary re-renders. The paragraph also highlights that immediately after a state update, the state variable still holds the previous value until the re-render occurs, a concept known as 'stale state'.
💡 Advanced Batching Scenarios and React 18
This paragraph discusses advanced scenarios where state update batching becomes relevant, such as timeouts, promises, and native DOM event handlers. Before React 18, batching only occurred in event handlers, but React 18 introduced automatic batching in these other situations for better performance. The paragraph also mentions the ReactDOM.flushSync function to exclude specific updates from batching in rare problematic cases. It concludes by emphasizing the importance of understanding batching behavior, especially when working with older React versions.
Mindmap
Keywords
💡Render phase
💡Key prop
💡State updates
💡Batching
💡Asynchronous state updates
💡Callback function
💡React 18
💡ReactDOM.flushSync
💡Performance optimization
💡Fiber tree
Highlights
React batches multiple setState calls into a single state update for the entire event handler, triggering only one re-render and commit phase.
Batching state updates is a performance optimization in React, as it avoids unnecessary re-renders and wasted renders.
When referencing a state variable immediately after updating it, the variable still holds the previous state value until the re-render occurs.
Updating state in React is asynchronous because the updated state is only available after the re-render, not immediately after the setState call.
To update state based on the previous state in the same event handler, use a callback function with setState instead of passing a single value.
Before React 18, automatic batching only occurred in event handlers, but not in situations like timeouts, promises, or native DOM events.
React 18 introduced automatic batching everywhere in the code, including timeouts, promises, and native DOM events.
In rare situations where automatic batching is problematic, you can use ReactDOM.flushSync to exclude a state update from batching.
Batching state updates is a performance optimization that avoids unnecessary re-renders and wasted renders.
When referencing a state variable immediately after updating it, the variable still holds the previous state value until the re-render occurs.
Updating state in React is asynchronous because the updated state is only available after the re-render, not immediately after the setState call.
To update state based on the previous state in the same event handler, use a callback function with setState instead of passing a single value.
Before React 18, automatic batching only occurred in event handlers, but not in situations like timeouts, promises, or native DOM events.
React 18 introduced automatic batching everywhere in the code, including timeouts, promises, and native DOM events.
In rare situations where automatic batching is problematic, you can use ReactDOM.flushSync to exclude a state update from batching.
Transcripts
So we have dived really deep
into some aspects of the render phase,
like the rules for render logic, and how the key prop works.
But now let's take one step back,
and go back to one very important aspect
of the first triggering phase,
which is the fact that state updates are batched.
So in that first lecture about how rendering works,
we had this sentence, which says
that renders are not triggered immediately.
And so in this lecture I want to focus on this part
which says that there is also batching
of multiple setState calls.
Now, as always, the easiest way of explaining
difficult concepts is by using a small code example.
So here we have three pieces of state,
defined using the useState hook,
and we also have a button in the user interface.
Then whenever there is a click on the button,
the event handler function named reset is called.
In this function, the three pieces of state,
answer, best, and solved,
are basically reverted back to their original state
and therefore, this function is called reset.
Now, actually this is the part
that interests us in this lecture.
And so let's now focus only on the event handler function.
Now what I want to do here is to analyze
how these three pieces of state
are actually updated behind the scenes.
So we might think that, as React sees
the set answer function call,
it would update the state to the empty string as requested,
and then trigger a re-render, and the commit phase,
then it would move on to the next line,
and to the same thing again,
and finally do the entire thing
one more time for the third state update.
So intuitively, we would think that,
if there are three state variables
being updated in this event handler,
then React would re-render three times, right?
However, this is actually not how it works.
So this is not how React updates multiple pieces of state
in the same event handler function.
Instead, these state updates will actually get batched
into just one state update for the entire event handler.
So updating multiple pieces of state
won't immediately cause a re-render for each update.
Instead, all pieces of state inside the event handler
are updated in one go.
So they are batched, and only then
will React trigger one single render and commit.
And conceptually, it makes sense that React works this way,
because if we're updating these pieces of state together,
it probably means that they should just represent
one new view, and therefore,
React only updates the screen once.
So if these date updates belong together,
it really wouldn't make much sense
to update the screen three times.
Doing so would also create two wasted renders,
because we're not interested in the first two renders,
only the final one, which already contains
all the three state updates.
Therefore, the fact that React
automatically batches state updates in this way
is yet another performance optimization
that React gives us out of the box.
Now, batching state updates is extremely useful,
but it can also have surprising results.
So let's turn our attention to this line of code now,
where we reference the answer state variable
right after updating it.
So what do you think will be the value
of this variable at this point?
Well, let's try to think about this.
So remember, that component state is stored
in the fiber tree during the render phase.
Now, at this point in the code,
the render phase has not happened yet.
So React is still reading the function line by line
to figure out what state needs to be updated,
but it hasn't actually updated the state yet,
and it also hasn't re-rendered yet.
That's the whole point of batching state updates
in the first place, right?
So what this means is that, at this point of the code,
the answer variable will still hold the current state.
So the state before the update,
even though we already told React to update it.
So at this point we say that our state is stale,
meaning that the state is no longer fresh and updated,
because in fact, a state update will only be reflected
in the state variable after the re-render.
And so for this reason, we say that updating state in React
is asynchronous, and again, it is asynchronous
because React does not give us the updated state variable
immediately after the set answer call,
but only after the re-render has happened.
Now, the same thing is also true
whenever there is only one piece of state being updated.
So no matter how many state variables are being updated,
the updated state is only available
after the re-render, not immediately.
Now, sometimes we actually do need the new value
immediately after updating it, and in the case,
that we need the new value
in order to update the same state again.
Or in other words, if we need to update state based
on a previous state update in the same event handler,
we can pass a callback function into the set state function
instead of a single value.
And we have actually done this in practice
all the time, right?
Now, so far, we have only talked about batching
in event handler functions, like our reset function.
That's because before React 18,
React only did automatic batching in event handlers,
but not in situations that happen
after a browser event has already happened.
However, there are certain very important situations
in which we do need to update state,
long after a browser event, like a click, has happened.
Examples of that are timeouts and promises,
for instance, we might want to run our reset function
only a second after a click event,
or we might want to run it after some data has been fetched.
So it would be nice to also have automatic batching
in those situations to improve performance, right?
Well, that's actually one of the important features
that React 18 gave us.
So before React 18, if this reset function
was called by a timeout, or by a promise,
state updates inside the function would not be batched.
Instead, in these situations, React would actually
update the state variables one by one, and therefore,
in this case, render three times.
Now another case is handling native events using DOM methods
such as addEventListener, where state updates
also used to not be batched, but now they are.
So again, if you're using the latest React version,
you will now get automatic batching all the time,
everywhere in your code.
And if, for some reason, you are working
with an older version of React, maybe at your work,
it's important that you know that batching used to work
in a different way before version 18.
Now, there are also some extremely rare situations
in which automatic batching can be problematic.
So if you ever find yourself in a situation like that,
you can just wrap the problematic state update
in a ReactDOM.flushSync function,
and React will then exclude that update from batching.
But you will most likely never need this.
I'm just mentioning this here,
so that you know that it exists.
Now, okay, and that's it about state update batching.
It turned out to be a bit longer than I thought,
but as always, there is just
so much interesting stuff to learn,
and so I hope that you don't mind at all.
But in any case, let's quickly go to the next video,
so I can show you some of this in practice.
関連動画をさらに表示
State Update Batching in Practice | Lecture 133 | React.JS 🔥
1 month of content in 1 hour | Updated guide to content batching & planning + free content calendar!
What are React updater functions? 🔄
Introduction to Redux | Lecture 257 | React.JS 🔥
How NOT to Fetch Data in React | Lecture 139 | React.JS 🔥
Understanding memo | Lecture 242 | React.JS 🔥
5.0 / 5 (0 votes)