One user action crosses several versions of reality
Trace browser draft, server state, and an in-flight request without mixing them.
A form can contain a local draft, a last-confirmed server value, and a pending change at the same time. These are different facts. Collapsing them into one variable makes the interface lie when a request is slow or fails. Give each fact an owner and define when information moves between them.
The server owns the persisted business record. The browser owns unsent input and interaction state such as which field has focus. A query cache holds a copy of server data with an age and identity. A pending mutation describes an intention whose outcome may still be unknown. The URL can own shareable navigation state such as the selected project or page. These ownership choices determine recovery after refresh, browser back, and reconnect.
React documents that each render sees a snapshot of state. A callback can therefore refer to values from the render that created it. This is useful, but it becomes a bug when code assumes an old callback automatically sees a later selection. Effects synchronize with external systems; they should not be used to maintain every value that can be calculated directly from current inputs.
A response also belongs to the request that produced it. If a user switches from project A to project B while A is loading, the late response for A must not overwrite B's display. Cancellation can save work, but identity checks still matter because a response may already be in flight. Store or compare the requested resource identity before accepting data into the visible state.
Worked example
A fictional settings form begins with confirmed title Cedar at version 7. The user types Maple. The browser holds draft Maple while confirmed remains Cedar. Save creates mutation M1 with expected version 7. Before the response arrives, the user types Birch. The server confirms Maple at version 8. The interface updates confirmed to Maple but preserves the newer unsent draft Birch.
Blindly assigning the response title to the input would erase the user's later work. Blindly marking Birch saved would claim a write that never occurred.
Represent the facts separately
A state record can make the save contract inspectable. This is teaching pseudocode, not a framework-specific implementation. It separates the confirmed version from the current draft and from the payload that one pending save actually sent.
The local draft revision answers whether the user edited after the save began. The server version answers which persisted record the save was based on. They are not interchangeable counters. A local revision can advance without a server write. A server version can advance because another user changed the record.
On a successful M1 response, update the confirmed record only according to the server's version contract. If the draft still has revision 11, the application can mark that draft clean and align it with the confirmed value. If the draft is revision 12, keep it dirty because Birch was never submitted by M1. Avoid a global saved flag that loses this distinction.
Trace two saves and one conflict
Step
Browser action
Server evidence
Visible truth
1
M1 sends Maple from v7
Pending
Maple pending
2
User types Birch
None
Birch unsaved
3
M2 sends Birch from v7
Pending
Two attempts tracked
4
M1 commits v8
Maple confirmed
Birch remains draft
5
M2 conflicts on v7
No Birch commit
Show conflict, preserve Birch
A product can choose to serialize saves so M2 waits for M1, or permit overlap with explicit conflict handling. Neither choice should be accidental. Serializing reduces one class of conflict but still needs to handle another user's changes. Overlap can improve responsiveness but makes operation and version tracking more important.
For a separate arrival-order case, M1 commits v8 but its response is delayed. A confirmed read reveals v8; the user reconciles and submits a new operation M3 with expected version 8, which commits v9. A later M1 response must not downgrade confirmed state from v9 to v8. This is a new authorized intent, not a retry of the rejected M2 with a changed payload. Compare authoritative versions or use a mutation reconciliation strategy that knows which response belongs to which operation. Arrival time alone does not define the latest persisted record.
Navigation and draft lifetime
Decide whether unsaved drafts persist when users navigate. A simple form may ask before discarding. A more capable editor may store drafts keyed by record and account. The correct policy depends on user expectations and data sensitivity. The important requirement is that a late response for P8 cannot update the form currently showing P9.
A shared query cache can accept P8's confirmed response under P8's key even when P8 is no longer visible. That is different from writing into the current input. If the account changes, account identity belongs in both draft and query keys where it affects access. A local draft containing private data should not appear when another account signs in on the same device.
Do not use an Effect to copy every server response into the draft without checking draft state. Such an Effect may erase typing whenever background revalidation occurs. Instead, define when the draft initializes, when it becomes dirty, and when a confirmed save or explicit reset may replace it. Derived values such as isDirty can be calculated from the appropriate state rather than maintained through another synchronization loop.
Misconceptions to correct
The first misconception is that the most recently received response is the newest truth. Network completion order can differ from server commit order and from user interaction order. Resource and version identity determine placement.
The second misconception is that setting state changes every existing callback's captured values. React's snapshot model means a callback can retain values from its creating render. Use functional updates or explicit dependencies where appropriate, but do not assume those tools solve the separate server-version contract.
Extend the exercise
Start with confirmed v10 and a clean draft. A background read returns v11 while the user has an unsaved draft based on v10. Propose behavior that preserves both facts. The model answer updates or records the newer confirmed state without silently replacing the draft, then exposes a conflict or reconciliation choice before save. Award one point for preserving input, one for recognizing the new server version, and one for avoiding a false saved label.
Exercise and solution
The user switches to project B before M1 returns. What should happen? Update A's cached confirmed record if appropriate, but do not replace B's form. The mutation must retain its resource identity. Award one point for preserving B, one for attaching the result to A, and one for distinguishing saved Maple from unsent Birch.
Interview probe and wrap-up
Why is a boolean loading flag insufficient? A strong answer identifies which request, resource, and mutation the flag describes. Follow up with two concurrent saves. A weak answer adds a longer debounce and assumes the race disappears. Draw the state timeline and keep user intent separate from confirmed storage.
AThe order in which HTTP responses must arrive.BThe server's globally committed record version.CChanges to the user's local draft, including unsent edits.DThe revision of the last submitted payload only.
M1 saved revision 11; current draft is revision 12. What may M1 success mark clean?
AOnly the submitted revision, preserving the newer dirty draft.BThe newer draft because its text was visible at reply time.CEvery current input field regardless of later edits.DThe entire record in every browser.
Confirmed v9 exists when an older v8 response arrives. Which rule prevents downgrade?
AAlways accept the latest network response.BReset to the original draft before applying it.CClear all pending operations without inspecting them.DUse the authoritative version/operation reconciliation contract.
A handler created while project A is selected schedules a callback. Before it runs, a new render selects B. The callback reads the selectedProject variable captured by the original handler. Which behavior should the design account for?
ARe-rendering rewrites selectedProject inside all earlier callbacks.BThe callback can still read A; bind its action to the intended project and check the current view before applying its result.CA functional update to an unrelated loading flag changes that captured project to B.DA longer delay guarantees the callback reads B.
A user switches accounts. Which draft-key design prevents accidental cross-account display?
AOne shared draft for the whole application.BRecord ID only, regardless of account scope.CAccount plus record identity where the data is account-specific.DRecord identity plus the last response timestamp, without account scope.
Can you explain local draft revision versus server version, then trace two saves, a background refresh, and navigation without erasing unsent work? State the relevant identifiers, failure boundary, and evidence in your own words before selecting your confidence.