Question presented to candidate: "Two sibling components need to stay in sync. Walk me through how you would handle that."
What a strong answer should cover:
- Siblings cannot talk to each other — that would be a sideways flow React does not have. You move the shared state up to their nearest common ancestor.
- The ancestor becomes the single source of truth and passes the value down to one child and a setter callback to the other.
- It is the direct consequence of
unidirectional data flow, not a separate technique. - Lift to the nearest common ancestor. Hoisting to the root re-renders the whole tree for a change two components care about.
- The trade: more prop passing, and every intermediate component re-renders.
- When lifting starts to hurt — deep trees, many consumers — the next steps are composition, Context, or a store. Reaching for Context immediately is the common overcorrection.
- The mirror technique, moving state down, matters just as much: state that only one subtree needs should live there, not above it.
- Controlled components are lifting state up applied to a form input: the value lives in the parent, not the DOM.
Clarifying questions expected:
- "How far apart are these components, and does anything between them need the value?"
- "Is this genuinely shared, or does each component need its own copy?"
Code / implementation expected: Yes — two inputs kept in sync through a shared parent is the canonical demonstration.