Lifting State and Keys

Lifting State Up and Resetting with Keys

When two components need the same value, neither can own it. Move the state to their closest common parent and pass it down: the value as one prop, the setter as another. The children become controlled by the parent, and there is exactly one copy of the truth.

State lifted to the parent, and a subtree reset with a keyJavaScript
function Chat({ contact }) {
  const [text, setText] = useState('');
  return <textarea value={text} onChange={e => setText(e.target.value)} />;
}
function Messenger({ contacts }) {
  const [to, setTo] = useState(contacts[0]);        // the shared value lives here
  return (
    <>
      <ContactList contacts={contacts} selected={to} onSelect={setTo} />
      <Chat key={to.id} contact={to} />             {/* new key: new Chat, empty draft */}
    </>
  );
}

ContactList no longer remembers which row is highlighted; it renders selected and reports clicks through onSelect. That is the whole pattern, and it is why so much React 7,897 code ends up as a stateful container with stateless leaves.

The key on <Chat> solves a different problem. React identifies a component by its position in the tree, so switching contacts would reuse the same Chat and keep a half-typed message meant for someone else. A changing key says the two are not the same component: the old unmounts, its state and effects go, and a fresh one mounts with text back to ''.

The same two children before and after the shared value is lifted into the parent
The same two children before and after the shared value is lifted into the parent