Queueing State Updates
Queueing State Updates
One action awards three participation points. Calling the setter three times with score + 1 looks reasonable, but every expression uses the same render’s score. We need to express three successive changes rather than three identical replacements.
React queues state updates and normally processes event-handler updates together. A functional updater receives the pending state from the queue, returns the next value and allows later updaters to build on that result.
Explain
Trace three updater functions from zero to three points.
Trace
Distinguish replacing state from transforming a queued value.
Apply
Keep an updater pure so React can safely evaluate it again.
Queued Updates: follow the relationship
Start: 0 points
React starts processing from the current stored value.
Apply queued updaters
Three pure n => n + 1 steps produce 1, then 2, then 3.
Next screen: 3 points
React displays the final result after processing the updates.
Build the mental model
Distinguish a replacement value from an update rule. setScore(score + 1) calculates a number immediately from the current snapshot. setScore(previous => previous + 1) supplies a rule to apply to the queued value. Repeating these forms has different consequences.
Trace the queue on paper
Write each queued item as either replace with a value or calculate from the pending value. Start with the current state and apply the queue in order. This small trace explains mixed updates more reliably than counting setter calls. A replacement discards the previously accumulated pending result at that point.
Do not assume each setter creates an intermediate screen that a user will see. The important observable result is the committed interface after React processes the update. If an application genuinely requires sequential visible phases, express those phases as intentional state and interactions rather than relying on setter timing.
Read the complete React example
The example starts at zero and queues three updater functions. Their inputs are zero, one and two, so the final score is three. The practice first queues a replacement of five and then an updater that adds two, giving seven.
React · JavaScript with JSX
import React, { useState } from 'react';
export default function App() {
const [score, setScore] = useState(0);
function award() {
setScore(previous => previous + 1);
setScore(previous => previous + 1);
setScore(previous => previous + 1);
}
return <main><p>Points: {score}</p><button onClick={award}>Award three points</button></main>;
}Expected screen and behavior
Initial screen: Points: 0 Award three points
After selecting Award three points: the screen includes Points: 3.Connect the source to the screen
React · main example
import React, { useState } from 'react';
export default function App() {
const [score, setScore] = useState(0);
function award() {
setScore(previous => previous + 1);
setScore(previous => previous + 1);
setScore(previous => previous + 1);
}
return <main><p>Points: {score}</p><button onClick={award}>Award three points</button></main>;
}React waits until the handler finishes before applying the grouped interface update. The queue describes the pending value, not a sequence of three immediately visible screens. Separate intentional clicks are separate events; batching does not mean all future clicks share one permanent snapshot.
Follow each queued calculation
React · three queued updaters
import React, { useState } from 'react';
export default function App() {
const [score, setScore] = useState(0);
function award() {
setScore(previous => previous + 1);
setScore(previous => previous + 1);
setScore(previous => previous + 1);
}
return <main><p>Points: {score}</p><button onClick={award}>Award three points</button></main>;
}The current score is 0. One click queues three updater functions; each receives the result of the preceding update rather than rereading the handler’s original score. The first computes 0 + 1 = 1, the second computes 1 + 1 = 2, and the third computes 2 + 1 = 3. The next screen therefore displays Points: 3.
If all three calls instead passed score + 1, each expression in this handler would read the same snapshot of 0 and request the replacement value 1. Three replacement requests for 1 do not add up to 3. The number of setter calls alone does not determine the final value; what each queued request means matters.
On another click, the stored score starts at 3 and the three updater functions produce 4, 5 and 6. Keep those functions pure: sending a notification inside an updater would mix a calculation with an external action that React might evaluate again.
Avoid the common mistakes
Keep updater functions pure. Do not send a network request, alert the user or mutate records inside an updater. React may evaluate them more than once in development checks. Use the event handler for event-related side effects and the updater for calculating state.
Practice before reading the solution
React · starting example
import React, { useState } from 'react';
export default function App() {
const [score, setScore] = useState(0);
function award() {
setScore(previous => previous + 1);
setScore(previous => previous + 1);
setScore(previous => previous + 1);
}
return <main><p>Points: {score}</p><button onClick={award}>Award three points</button></main>;
}Reset bonus points to five and add two in the same action.
Predict the initial visible text and explain which values determine it. Then inspect the worked solution below. Change one relevant input in your local project and check whether the screen follows your prediction. A working screen should be checked for the intended meaning, not merely the absence of an error.
Worked practice solution
The solution intentionally mixes a replacement and an updater to demonstrate ordering. The updater sees the five queued before it rather than the earlier zero. Reversing those two calls would make the final replacement win and produce five.
React · JavaScript with JSX
import React, { useState } from 'react';
export default function App() {
const [bonus, setBonus] = useState(0);
function award() {
setBonus(5);
setBonus(previous => previous + 2);
}
return <main><p>Bonus: {bonus}</p><button onClick={award}>Set and add bonus</button></main>;
}Expected screen and behavior
Initial screen: Bonus: 0 Set and add bonus
After selecting Set and add bonus: the screen includes Bonus: 7.Check your reasoning
React · main example
import React, { useState } from 'react';
export default function App() {
const [score, setScore] = useState(0);
function award() {
setScore(previous => previous + 1);
setScore(previous => previous + 1);
setScore(previous => previous + 1);
}
return <main><p>Points: {score}</p><button onClick={award}>Award three points</button></main>;
}Choose the explanation that matches React and JavaScript behavior. Review the reasoning for each alternative before moving on.
Use the idea in the next lesson
React queues state updates and normally processes event-handler updates together. A functional updater receives the pending state from the queue, returns the next value and allows later updaters to build on that result.
Continue with Updating Objects in State. Revisit State as a Snapshot when the relationship between inputs and the resulting screen needs another look.
Read the primary reference: React documentation on Queueing State Updates.
Reaching the recap and completing the quizzes are separate milestones.