Resetting the Small App
The lesson planner now stores three independent values.
const [query, setQuery] = useState("");
const [showCompleted, setShowCompleted] = useState(true);
const [weeklyGoal, setWeeklyGoal] = useState("3");A Reset button should return those values to the planner's initial state. The filtered list, visible count, goal validity, and labels need no reset because they are derived during rendering.
This distinction gives the reset handler a precise job. Reset stored values and let the next render recalculate every consequence.
Reset Direct State with Direct Setters
Define the initial values outside the component.
const initialQuery = "";
const initialShowCompleted = true;
const initialWeeklyGoal = "3";Use the same constants for initialization.
const [query, setQuery] = useState(initialQuery);
const [showCompleted, setShowCompleted] = useState(initialShowCompleted);
const [weeklyGoal, setWeeklyGoal] = useState(initialWeeklyGoal);Reset from one event handler.
function handleReset() {
setQuery(initialQuery);
setShowCompleted(initialShowCompleted);
setWeeklyGoal(initialWeeklyGoal);
}React batches the three updates and renders the planner with one consistent next state.
The Reset control performs an action and does not submit the form.
<button type="button" onClick={handleReset}>
Reset
</button>Reset the independent state values. Derived values will recalculate from them during the next render.
Keep Initialization and Reset in Agreement
Repeated literal values can drift.
const [weeklyGoal, setWeeklyGoal] = useState("3");
function handleReset() {
setWeeklyGoal("5");
}The component initializes to three and resets to five. That can be intentional, but the source does not explain two defaults.
A named constant declares one policy.
const initialWeeklyGoal = "3";Use it in both locations. If reset should use a different product value, give that value another name such as recommendedWeeklyGoal and explain the difference in UI.
Reset Object State with a Fresh Value
A grouped planner object can have a factory function.
function createInitialPlanner() {
return {
query: "",
showCompleted: true,
weeklyGoal: "3",
};
}Initialize lazily.
const [planner, setPlanner] = useState(createInitialPlanner);Reset by calling the factory.
function handleReset() {
setPlanner(createInitialPlanner());
}Each call returns another object. Nested mutable values should also be created fresh when the application can update them.
function createInitialPlanner() {
return {
query: "",
selectedIds: [],
};
}Do not keep one shared initial object and later mutate it.
const initialPlanner = { query: "" };
initialPlanner.query = "state";The next reset would reuse the mutated value.
Separate state variables remain clearer for the three-field milestone. The factory pattern becomes useful when several fields truly change together.
Controlled Fields Ignore Native Reset Unless State Changes
HTML forms support native reset behavior.
<button type="reset">Reset</button>For an uncontrolled input, the browser can restore defaultValue.
<input name="query" defaultValue="" />A controlled input receives its value from React state.
<input value={query} onChange={handleQueryChange} />Resetting only the DOM cannot replace query. The next render supplies the state value again.
Handle the form's reset event and update controlled state.
function handleFormReset(event) {
event.preventDefault();
handleReset();
}<form onReset={handleFormReset}>
<button type="reset">Reset</button>
</form>An ordinary type="button" with onClick={handleReset} is simpler when no native reset behavior is needed.
State Is Associated with Tree Position
React retains state for a component type at a position in its parent tree.
function App() {
return (
<main>
<LessonPlanner />
</main>
);
}When App renders again and returns LessonPlanner at the same position with the same type, React can preserve that planner instance and its state.
Changing unrelated props on the parent does not reset the child automatically.
function App({ theme }) {
return (
<main className={theme}>
<LessonPlanner />
</main>
);
}LessonPlanner remains the first child of main with the same component type. Its query can remain intact.
React associates state with a rendered component instance identified through its type, parent position, and key.
Conditional Source Can Preserve the Same Position
This source uses two branches.
function App({ compact }) {
return compact
? <LessonPlanner compact />
: <LessonPlanner compact={false} />;
}Both branches place a LessonPlanner at the component's returned root position. React sees the same type at the same position and preserves its state while changing the prop.
This source changes the type.
function App({ compact }) {
return compact
? <CompactPlanner />
: <LessonPlanner />;
}React removes one type and creates the other. Local state below the replaced type starts from its initializer.
Do not declare separate components only to reset state. Use direct state updates when the same component identity remains correct.
Nested Component Definitions Cause Accidental Resets
This component type is recreated whenever App renders.
function App() {
function LessonPlanner() {
const [query, setQuery] = useState("");
return <input value={query} onChange={(event) => setQuery(event.target.value)} />;
}
return <LessonPlanner />;
}The next App render creates another LessonPlanner function reference. React treats it as another component type and resets the state below it.
Declare the component at module level.
function LessonPlanner() {
const [query, setQuery] = useState("");
// ...
}
function App() {
return <LessonPlanner />;
}Changing the key changes the component identity at that position, so React starts a fresh state instance.
Component function names can look identical while their function references differ. Keep component definitions at module level.
Change a Key for a New Record Identity
An editor can occupy the same tree position while representing another lesson.
<LessonEditor lesson={selectedLesson} />If LessonEditor initializes a draft from selectedLesson.title, changing the prop alone preserves the existing local draft. That can leave text from the previous lesson.
Use the record ID as a key when selecting another lesson should create another editor instance.
<LessonEditor
key={selectedLesson.id}
lesson={selectedLesson}
/>When the ID changes, React removes the previous editor instance and creates one for the next identity. All local state and host nodes below that editor restart.
This is broader than resetting one input. It affects the whole keyed subtree.
Use a key reset when the component represents another identity. Use setters when the same instance should return selected fields to defaults.
Never Generate a Reset Key During Render
This key changes on every render.
<LessonPlanner key={Math.random()} />Every state update causes the parent to produce another key. React removes the current planner and creates a new one, so the input cannot retain typed text.
This form has the same failure.
<LessonPlanner key={crypto.randomUUID()} />The generated value is unique but not stable. Keys must identify retained records and instances across renders.
Use a stable ID from the represented data.
<LessonPlanner key={reader.id} />The planner now resets only when the selected reader identity changes.
Reset State that Follows the Same User Action
Submitting a search can clear a previous submission message.
function handleQueryChange(event) {
setQuery(event.target.value);
setSubmitted(false);
}The edit starts another validation attempt, so the same event requests both updates.
Resetting the whole planner can also clear submission state.
function handleReset() {
setQuery(initialQuery);
setShowCompleted(initialShowCompleted);
setWeeklyGoal(initialWeeklyGoal);
setSubmitted(false);
}Do not reset unrelated state. A theme preference stored above the planner should remain unchanged. A server-saved goal should not be deleted merely because the local filter reset.
The handler should name the product operation it performs. handleResetPlanner is clearer after a page gains several resettable regions.
Preserve Focus During Reset
Direct state reset keeps the existing input DOM nodes when their element types and positions remain stable. Focus can therefore remain on the Reset button after activation.
A key reset recreates the subtree and can remove the currently focused node. The browser then needs an intentional focus result.
Avoid key resets for ordinary field clearing because DOM recreation adds focus and accessibility consequences. Direct setters update values while retaining the component and controls.
Choose the smaller reset that preserves the existing host structure and avoids unnecessary focus loss.
Assemble the Planner in Small Sections
Keep the static lesson data outside the component.
const lessons = [
{ id: "events", title: "Click Handlers", complete: true },
{ id: "state", title: "First useState", complete: true },
{ id: "forms", title: "Form Inputs", complete: false },
];Declare the independent state.
function LessonPlanner() {
const [query, setQuery] = useState("");
const [showCompleted, setShowCompleted] = useState(true);
const [weeklyGoal, setWeeklyGoal] = useState("3");
// ...
}Derive the visible lessons from current state.
const normalizedQuery = query.trim().toLowerCase();
const visibleLessons = lessons.filter((lesson) => {
const matchesText = lesson.title.toLowerCase().includes(normalizedQuery);
const matchesStatus = showCompleted || !lesson.complete;
return matchesText && matchesStatus;
});Add the direct reset.
function handleReset() {
setQuery("");
setShowCompleted(true);
setWeeklyGoal("3");
}Render labeled controlled fields and the list as small components. The complete application remains readable because each component performs one visible job.
Review the Completed Interaction
Trace one query edit.
input change event
-> handler requests next query
-> React renders with that query snapshot
-> component derives visibleLessons
-> React DOM commits list changesTrace Reset.
button click event
-> handler queues three initial values
-> React batches the requests
-> component renders one reset snapshot
-> derived values recalculate
-> React DOM commits required form and list changesNo effect is needed. No random key is needed. No derived count needs its own setter.
Check the Interaction Model
The application uses these runtime relationships.
event props connect handlers to semantic controls
useState retains values per component instance
handlers read one render snapshot
setters queue batched updates
controlled inputs display state values
derived UI calculates from current values
direct setters reset the same instance
stable keys identify when a whole instance should restartSource Notes
- React documentation, Preserving and Resetting State
- React documentation, Queueing a Series of State Updates
- React documentation, Choosing the State Structure
- React DOM reference,
form