skip to content

In a React master-detail editor, remounting the detail pane with key={recordId} correctly clears it but also throws away unsaved edits when the user clicks another record and comes back. How do you decide between identity-keyed remount and keeping per-record draft state, and what does each choice commit you to?

level: principalimportance: should knowfreq 30%

answer

  1. the key encodes a product decision
  2. ask per slice: gone or exactly as I left it
  3. nothing inside the boundary can outlive it
  4. drafts hoisted above become your lifecycle
  5. preservation buys growth, staleness, conflicts

basics

~20 s

Decide by whether losing the state is the intended product behaviour. If edits are disposable, keyed remount is the simplest correct answer. If they are work the user expects back, the draft must live above the keyed boundary, keyed by record id, and you own its lifetime.

solid answer

~50 s

Remount-by-key is a *policy*, not just a technique: it declares that state inside is worthless once the identity changes. That is right for filters, validation errors and short forms, and it costs almost nothing to maintain. The moment the product says "do not lose my edits", no key placement helps — anything inside the boundary dies — so the drafts must be hoisted above it into a map from record id to draft, or into persistence, and the keyed component becomes a view seeded from that map. What you take on then is real: unbounded growth, staleness against the server when the record changes underneath, an explicit discard path because remount is no longer the eraser, conflict handling on save, and restoring scroll and focus yourself. I make that choice per surface and write it down, because the two behaviours are indistinguishable in code review and very different to a user.

go deeper

for a junior

Understand that a keyed remount deletes the state inside it, so anything a user should get back cannot be stored in that component.

for a middle

Explain where preserved drafts have to live instead — above the keyed boundary, keyed by record id — and how the keyed component seeds itself from that data on mount.

for a senior

Judge per slice of state whether losing it is the intended behaviour, and account for the operational cost of preservation: growth, staleness against the server, clearing on save, restoring focus and scroll.

for a principal

Own it as a policy. Decide which surfaces promise to keep work, write the convention down so it is not re-litigated per screen, and make sure users get a consistent, trustworthy answer to whether their typing is safe.

## The decision is about semantics, not mechanics Both options are easy to implement. The question an interviewer is really asking is whether you notice that `key={recordId}` encodes a product decision — *switching records destroys what you typed* — and whether you would make that decision deliberately. So the first move is to name the state and ask, for each slice, what should happen when the user returns to this record: gone, or exactly as I left it? - **Gone** fits transient interaction state: which tab was open, validation errors from a previous attempt, a half-typed filter, a freshly-opened create form. - **Preserved** fits work: a long-form edit, a partially filled multi-step submission, anything the user would be annoyed to retype. Most real screens are a mix, which is why this rarely resolves to one global answer. ## If the answer is "gone": keep the key Identity-keyed remount is the cheapest correct implementation and it has properties worth defending. The reset is total, so no field can be forgotten. It is visible in the tree, so a reviewer sees the boundary. It has no ongoing maintenance cost as fields are added. And it composes with the alternative later — you can always hoist state out of the keyed component when the requirement changes. What you commit to: the mount cost on every switch, losing focus and scroll inside the boundary, and re-running whatever the subtree does on mount. Keep expensive or imperative widgets outside the keyed component so the remount stays cheap. ## If the answer is "preserved": the draft must outlive the instance Because a remount destroys everything below the key, preserved drafts cannot live in the keyed component's `useState` or in a ref inside it. They have to live somewhere with a longer lifetime: - a map from record id to draft held by an ancestor above the keyed boundary; - the same map in a client store, when many distant parts of the app need it; - browser storage, when the draft must survive a reload; - the server, when it must survive the device. The keyed component can stay, which is often the nicest shape: it remounts on switch and seeds itself from the map for the new id, so the reset logic remains structural while the durable data sits above it. ```jsx function Editor({ recordId, drafts, onDraftChange }) { return ( <DetailPane key={recordId} initialDraft={drafts[recordId] ?? emptyDraft} onChange={next => onDraftChange(recordId, next)} /> ); } ``` ## What preservation actually costs This is where a principal-level answer separates itself. Once drafts outlive the component, you own their whole lifecycle: 1. **Growth.** A map keyed by id grows with every record touched. Decide on a cap, an eviction policy, or clearing on save and on navigation away from the feature. 2. **Staleness.** The underlying record can change on the server while a draft sits in memory. You need a rule: last-write-wins, warn on conflict, or store the version the draft was based on and compare at save time. 3. **An explicit discard path.** Remount is no longer the eraser, so the user needs a visible way to abandon changes, and the code needs a deliberate clear on successful save. 4. **Continuity beyond state.** Scroll position, caret and focus are still destroyed by the remount, so if the promise is "exactly as I left it", those have to be captured and restored on purpose. 5. **Correctness of scope.** A draft keyed by record id is wrong the moment the same record can be edited in two places at once; then identity includes the surface, not just the record. 6. **Trust.** Preserved drafts that silently disappear later are worse than never preserving them. If you promise persistence, it has to be reliable, including across reloads if that is what users will infer. ## The hybrid that usually wins In practice the durable answer is: preserve only what is expensive to recreate, and keep everything else identity-scoped. Hoist the text of a long edit; let tab selection, validation state and scratch UI die with the remount. The keyed boundary stays as the default eraser, and the exceptions are explicit and few, which also keeps the memory and conflict story small. ## Make the choice legible Because both behaviours look identical in a diff, the decision belongs in a written convention: which surfaces preserve drafts, where preserved state lives, when it is cleared, and what the user sees when work is about to be discarded. Otherwise every new screen re-litigates it, some preserve by accident, and users cannot form a reliable expectation about whether their typing is safe.

  • Where would you put the drafts map so the keyed component still resets normally?
    In an ancestor rendered above the keyed boundary — component state for a single feature, a client store when several distant parts need it, storage when it must survive reload. The keyed pane keeps remounting and seeds itself from the map for the new id, so the structural reset stays and only the durable data moves up.
  • How do you decide when a preserved draft has become stale enough to discard?
    Tie it to a version of the record it was based on and compare at save or on reopen. Practical policies are: warn and let the user merge when the server version moved, drop drafts older than a session, and always clear on a successful save. The rule matters less than having one users can predict.
  • What signal tells you a team has drifted into accidental preservation?
    State that survives a record switch without anyone deciding it should — usually because it was lifted above the key for an unrelated reason, or because someone replaced a key with an effect-based reset. The tell is bug reports about one screen showing another record's values, and no written answer to which screens keep drafts.
  • Is there a case where you would deliberately preserve nothing, even for long edits?
    Yes — when a stale draft is dangerous rather than merely annoying: anything where resubmitting old content has legal or financial consequences, or where a second editor may have changed the record. There, forcing a fresh start on every switch and requiring an explicit save is the safer default, and the remount enforces it structurally.

saying these in an interview costs you the question

  • Treats the choice as a technique question with one right answer
  • Tries to save drafts in state inside the keyed component
  • Adds a drafts map with no eviction or clearing rule
  • Assumes preserved drafts remove the need for a discard action
  • Ignores that the record may change on the server meanwhile

context