Preserving and Resetting State
Preserving and Resetting State
A teacher types an attendance note for Asha, switches to Ravi, and sees Asha’s draft in Ravi’s editor. The application must decide whether the editor represents the same task or a new student task.
React preserves state for a component identity at a position in its rendered tree. Changing the component type or its key tells React to use a different identity, which resets that component’s state and the state below it.
Understand
Connect preserved state with component identity.
Build
Reset a student note editor with a deliberate key.
Check
Distinguish resetting from saving a draft elsewhere.
An identity change starts a fresh editor
Asha editor
The editor remembers a draft under key Asha.
Choose Ravi
The parent supplies key Ravi at that position.
Fresh state
A new editor starts with an empty note.
The position and identity matter
Rendering again does not normally erase state. That is why a counter survives changes to another nearby label. When React recognizes the same component type at the same place with the same key, its remembered values remain available. State belongs to that identity rather than to a particular invocation of the component function.
In a note editor, the student is part of the editor’s meaning. Giving NoteEditor a student key makes switching students a deliberate reset. key is special React information, so it is not a prop that NoteEditor can read. Pass student separately when the child also needs the student’s name.
Start a fresh note when the student changes
NoteEditor is declared outside App so its component type remains stable. App owns the selected student. The child owns the draft and receives a key based on the student name. This small example intentionally discards the previous draft when the teacher switches.
React · JavaScript with JSX
import { useState } from 'react';
function NoteEditor({ student }) {
const [note, setNote] = useState('');
return <section><h2>Note for {student}</h2>
<label>Attendance note <input value={note} onChange={event => setNote(event.target.value)} /></label>
<p>Draft: {note || '(empty)'}</p>
</section>;
}
export default function App() {
const [student, setStudent] = useState('Asha');
return <main><h1>Student notes</h1>
<button onClick={() => setStudent('Ravi')}>Choose Ravi</button>
<NoteEditor key={student} student={student} />
</main>;
}Expected screen and behavior
The initial Asha draft is empty. Type a note, then choose Ravi: the heading changes and the draft is empty again.Compare a render with a replacement
React · Start a fresh note when the student changes
import { useState } from 'react';
function NoteEditor({ student }) {
const [note, setNote] = useState('');
return <section><h2>Note for {student}</h2>
<label>Attendance note <input value={note} onChange={event => setNote(event.target.value)} /></label>
<p>Draft: {note || '(empty)'}</p>
</section>;
}
export default function App() {
const [student, setStudent] = useState('Asha');
return <main><h1>Student notes</h1>
<button onClick={() => setStudent('Ravi')}>Choose Ravi</button>
<NoteEditor key={student} student={student} />
</main>;
}Typing changes NoteEditor’s note state. React still recognizes the Asha editor and preserves its other information. Selecting Ravi changes App’s student state and therefore changes the child key. React removes the old child identity and creates the Ravi editor with its initial empty string.
Removing the key would let the same NoteEditor identity remain in that position. Its student prop would change, but its draft would still be Arrived late. Neither choice is automatically correct for every product: the teacher’s intended workflow decides whether the draft should survive. In this task, attaching a previous student’s note to a new name would be misleading.
Preserve drafts when the requirement changes
If teachers need to switch between students without losing work, store a notesByStudent map in the parent and supply each student’s current note. That is a different data model from resetting local state. A key reset does not save a draft and cannot bring it back after the old component was removed.
Place keys at the boundary whose state should restart. A key on a single input can replace the input element without resetting other state in its parent. A key on the editor resets all state inside the editor. Avoid arbitrary changing keys, which can unexpectedly lose focus and drafts on every render.
Try the school task
React · starting example
import { useState } from 'react';
function NoteEditor({ student }) {
const [note, setNote] = useState('');
return <section><h2>Note for {student}</h2>
<label>Attendance note <input value={note} onChange={event => setNote(event.target.value)} /></label>
<p>Draft: {note || '(empty)'}</p>
</section>;
}
export default function App() {
const [student, setStudent] = useState('Asha');
return <main><h1>Student notes</h1>
<button onClick={() => setStudent('Ravi')}>Choose Ravi</button>
<NoteEditor key={student} student={student} />
</main>;
}Add a Start over button that resets the current student’s editor without switching students. Keep the student heading unchanged and use a separate revision value as part of the child key. After typing a draft, clicking Start over should show the empty draft again.
Worked answer
The parent increments revision. The string key combines student and revision, so a new revision represents a fresh editing session. This answer demonstrates an intentional reset boundary; for a single field, directly clearing note in the child could also meet the requirement with less machinery.
React · JavaScript with JSX
import { useState } from 'react';
function NoteEditor({ student }) {
const [note, setNote] = useState('');
return <section><h2>Note for {student}</h2>
<label>Attendance note <input value={note} onChange={event => setNote(event.target.value)} /></label>
<p>Draft: {note || '(empty)'}</p>
</section>;
}
export default function App() {
const [revision, setRevision] = useState(0);
const student = 'Asha';
return <main><h1>New editing session</h1>
<button onClick={() => setRevision(value => value + 1)}>Start over</button>
<NoteEditor key={student + ':' + revision} student={student} />
</main>;
}Expected screen and behavior
Type a note for Asha. Start over clears the draft while the heading remains Note for Asha.Mistakes and boundaries
Do not define a component function inside another component merely to organize code. It creates a new component type when the parent renders and can cause unintended resets. Define stable component types outside the parent, then use props to provide changing information.
Keys are interpreted among siblings, not as global student storage slots. Rendering two different keyed positions does not share their state. Changing a key can also rerun Effects in the replaced subtree, so resetting an editor may replace subscriptions or other external connections owned inside it.
Check your reasoning
React · Start a fresh note when the student changes
import { useState } from 'react';
function NoteEditor({ student }) {
const [note, setNote] = useState('');
return <section><h2>Note for {student}</h2>
<label>Attendance note <input value={note} onChange={event => setNote(event.target.value)} /></label>
<p>Draft: {note || '(empty)'}</p>
</section>;
}
export default function App() {
const [student, setStudent] = useState('Asha');
return <main><h1>Student notes</h1>
<button onClick={() => setStudent('Ravi')}>Choose Ravi</button>
<NoteEditor key={student} student={student} />
</main>;
}Choose the answer that follows the data and the interaction, then read the explanation for each alternative.
Carry the idea forward
A rerender and a reset are different operations. Use stable identities to preserve work and intentional key changes to restart a task. Continue with useReducer when several related attendance updates need a clearly named set of transitions.
Read the primary reference: React: preserving and resetting state.
Reaching the recap and completing the quizzes are separate milestones.