State as a Snapshot
State as a Snapshot
A teacher increments a counter and then checks the variable in the same handler. It still contains the old value. Understanding why prevents incorrect announcements and predictions about the interface.
Each render sees a snapshot of state. The handlers created during that render close over that snapshot. A setter requests a later render but does not rewrite the current render’s variables or the functions already created from them.
Explain
Explain why a setter does not rewrite the current handler’s variables.
Trace
Predict the old handler value and the new displayed count.
Apply
Calculate a next mark explicitly when the same handler must announce it.
State Snapshots: follow the relationship
Current snapshot: 0
The count and handler were created for this render.
Request next count: 1
Calling the setter leaves the handler’s count at 0.
Next render: 1
The next screen reads 1; the recorded handler message still reports 0.
Build the mental model
Imagine a printed attendance sheet for one moment. Requesting an updated sheet does not change the numbers on the sheet in your hand. Likewise, the next render gets the new count while the current handler keeps reading the snapshot that created it.
A handler remembers its render
Snapshot behavior also applies to props and local calculations captured by a handler. A delayed attendance notification created when count is zero still refers to that render’s zero unless the design deliberately reads a separate current-value mechanism. Time passing alone does not change a closure’s captured bindings.
When an operation must use a freshly requested value, name the calculation explicitly as the practice does. When it must update based on whatever value is pending in the state queue, supply a functional updater. These solve different problems and should not be treated as interchangeable magic fixes.
Read the complete React example
The example captures the old count in a status message while requesting the next count. After the click, the screen displays a new count of 1 and a message saying the handler saw 0. These values describe different moments rather than a failed update.
React · JavaScript with JSX
import React, { useState } from 'react';
export default function App() {
const [count, setCount] = useState(0);
const [message, setMessage] = useState('No click yet');
function add() {
setCount(count + 1);
setMessage('Handler saw: ' + count);
}
return <main><p>Count: {count}</p><p>{message}</p><button onClick={add}>Add arrival</button></main>;
}Expected screen and behavior
Initial screen: Count: 0 No click yet Add arrival
After selecting Add arrival: the screen includes Handler saw: 0.Connect the source to the screen
React · main example
import React, { useState } from 'react';
export default function App() {
const [count, setCount] = useState(0);
const [message, setMessage] = useState('No click yet');
function add() {
setCount(count + 1);
setMessage('Handler saw: ' + count);
}
return <main><p>Count: {count}</p><p>{message}</p><button onClick={add}>Add arrival</button></main>;
}React renders after processing the update request. The next count and the message are both state values chosen by the handler. An asynchronous callback also retains the values from the render where it was created; waiting does not turn them into live references.
Avoid the common mistakes
Do not rely on reading count immediately after setCount to obtain the requested next count. Calculate nextCount in a local variable when the same handler needs it. When a later operation needs the latest queued value, a functional updater can express that dependency.
Practice before reading the solution
React · starting example
import React, { useState } from 'react';
export default function App() {
const [count, setCount] = useState(0);
const [message, setMessage] = useState('No click yet');
function add() {
setCount(count + 1);
setMessage('Handler saw: ' + count);
}
return <main><p>Count: {count}</p><p>{message}</p><button onClick={add}>Add arrival</button></main>;
}Increment a mark and announce the planned next mark accurately.
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 practice names nextMark before making either update request. The announcement uses that calculated value, so it agrees with the new screen. This does not change snapshot behavior; it avoids asking the old snapshot to act like a mutable live variable.
React · JavaScript with JSX
import React, { useState } from 'react';
export default function App() {
const [mark, setMark] = useState(40);
const [message, setMessage] = useState('No correction yet');
function correct() {
const nextMark = mark + 1;
setMark(nextMark);
setMessage('Next mark: ' + nextMark);
}
return <main><p>Mark: {mark}</p><p>{message}</p><button onClick={correct}>Correct mark</button></main>;
}Expected screen and behavior
Initial screen: Mark: 40 No correction yet Correct mark
After selecting Correct mark: the screen includes Next mark: 41.Check your reasoning
React · main example
import React, { useState } from 'react';
export default function App() {
const [count, setCount] = useState(0);
const [message, setMessage] = useState('No click yet');
function add() {
setCount(count + 1);
setMessage('Handler saw: ' + count);
}
return <main><p>Count: {count}</p><p>{message}</p><button onClick={add}>Add arrival</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
Each render sees a snapshot of state. The handlers created during that render close over that snapshot. A setter requests a later render but does not rewrite the current render’s variables or the functions already created from them.
Continue with Queueing State Updates. Revisit useState: Component Memory when the relationship between inputs and the resulting screen needs another look.
Read the primary reference: React documentation on State as a Snapshot.
Reaching the recap and completing the quizzes are separate milestones.