A detail panel keeps the previous item's unsaved edits after the user selects a different item; who should own that state?
answer
- state outlived its subject
- same instance, different inputs
- derive, re-identify, or reset
- identity reset forgets nothing, keeps nothing
- must the draft survive switching?
basics
~20 sThe panel owns draft state that outlives its subject. Either stop storing it and derive the fields from the selected item, give the panel a new identity per item so the old state is discarded, or reset deliberately on selection change.
solid answer
~50 sThe symptom says the panel owns state whose lifetime is tied to a subject it does not track: the same instance is reused across selections, so anything it holds survives unless something clears it. Three ownership answers exist. **Do not store it** — derive the displayed values from the selected item until the user actually edits, which removes the bug rather than handling it. **Tie the state's lifetime to the subject** by giving the panel a new identity per item, so the runtime discards the old instance and its state wholesale. **Keep the instance and reset explicitly** when the selection changes, which is precise but enumerates fields, so tomorrow's new field is forgotten. The choice is a product question too: if drafts must survive switching back and forth, the panel is the wrong owner altogether — the drafts belong above it, held per item by whoever owns the selection.
go deeper
Remember that a component's state belongs to the instance, not to the values passed into it. New inputs alone do not clear anything the component is holding.
Contrast the fixes: deriving from the subject, giving the instance a new identity so its state is discarded, or resetting deliberately — and say which one forgets fields and which one loses everything else.
Treat it as a lifetime question and check the product intent first: if the draft must survive switching, move ownership above the panel and hold one draft per item rather than resetting.
Name the policy: which state may be discarded silently, which must be preserved or confirmed, and where drafts live, so this is decided once instead of per panel by whoever hits the bug.
## What the bug is telling you A component's state has a lifetime: it is created with the instance and discarded with it. When a list selection changes, most runtimes reuse the same panel instance and hand it different inputs, because the shape of the tree has not changed. The panel's own cells are untouched by that. So a draft typed for item A is still there when item B is shown, next to item B's data — one instance, two subjects, and state that belongs to the first. That is not a framework quirk to work around. It is the correct behaviour for state whose owner did not say what its lifetime is, and the fix is an ownership decision. ## Three answers, and what each gives up | Approach | What it does | Gives up | |---|---|---| | Do not store it | Fields are derived from the selected item; state is created only when the user edits | Nothing, where the panel is mostly a view — this is the first option to try | | Tie lifetime to the subject | Give the panel a new identity per item, so the old instance and everything it held is discarded | Everything else the instance held: scroll position, focus, which section was expanded, in-flight work | | Reset deliberately | Keep the instance; clear the fields when the selection changes | Precision by enumeration — each field must be named, so a field added later is silently kept | The second row is deliberately coarse: its virtue is that it cannot forget a field, and its vice is that it cannot keep one. The third is the opposite. Choosing between them is choosing which mistake you would rather have, which is worth saying out loud in an interview. ## Where the draft really belongs Before reaching for a reset, ask whether losing the draft is the intended behaviour. Two products, two answers: - **Switching means discard.** The panel is a view onto the current selection and an unsaved edit is scratch work. Then a lifetime tied to the subject is exactly right, and the state belongs in the panel. - **Switching means park it.** The user expects to come back and find the edit. Then the panel cannot own the draft at all, because its state dies with whatever the panel's lifetime is. The drafts are lifted to the component that owns the selection, held per item, and the panel receives the draft for the current item as an input and requests changes to it. The second case is the one candidates miss. They fix the visible bug with a reset and ship a product decision — "your edit is gone" — without anyone choosing it. ## Pitfalls around resetting 1. **Resetting from a watcher on the input.** Reacting to "the subject changed" by writing the cells works, but there is a pass where the panel renders the new subject with the old draft, and the ordering between that write and other reactions becomes something you have to reason about. Resetting at the point where the selection is decided is easier to defend. 2. **Partial resets.** A reset that clears the fields but not the validation messages, the dirty marker, or the collapsed sections leaves a half-state that is harder to diagnose than the original bug, because part of the screen looks fresh. 3. **Confusing "the input changed" with "the user meant to discard".** The same input change happens when the underlying record is refreshed from elsewhere. Resetting on any input change throws away edits on a refresh; keying the decision to the subject's identity, not to any change in its contents, is what distinguishes the two. 4. **Silently dropping work.** If the draft has value, the honest options are to keep it (lifted, per item), to warn before discarding, or to save it. Clearing it quietly is a choice, and it should be one someone made. ## The general rule to carry away State's lifetime is part of its ownership. When you declare a cell, you are also saying how long the value should live — for the component's lifetime, for the subject's, or for the session. The bug in this scenario is a mismatch between the lifetime the state has and the lifetime the value should have, and each fix is a way of aligning them: derive it and it has no lifetime of its own, tie the instance's lifetime to the subject, or intervene at each subject change. Two components each holding their own draft for the same item is never one of the fixes; that is the duplication bug arriving under cover of a reset.
- Why does the panel keep the old draft at all, given its inputs changed?Because the runtime reused the same component instance — the tree's shape did not change, only the inputs. State cells belong to the instance, not to the inputs, so they survive. Nothing about receiving a new input clears state the component owns; only a write or the instance's disposal does.
- Drafts must survive switching between items. What changes about ownership?The panel stops owning the drafts. The component that owns the selection holds a draft per item and passes the current one down, so a draft's lifetime is tied to that owner rather than to the panel's instance. The panel becomes a view that renders the draft it is given and requests changes to it.
- Why is resetting inside a reaction to the input change considered a weaker option?It runs after the panel has already rendered the new subject with the old draft, so there is a visible intermediate state and an ordering question between that write and other reactions. Deciding the reset where the selection changes, or tying the state's lifetime to the subject, avoids the extra pass entirely.
saying these in an interview costs you the question
- Assumes state clears itself when a component receives new inputs
- Resets on any input change, discarding edits when the record is merely refreshed
- Clears the fields but leaves validation messages and the dirty marker behind
- Keeps a draft in the panel and a second copy above it, kept in step
- Discards unsaved work silently and calls it a bug fix
- Believes a new identity for the instance preserves scroll position and focus