Make the Entry Form Predictable
Open client/src/components/EntryForm.jsx.
The starter already keeps the entry fields in one React state object. Keep that structure because an entry is created or edited as one unit:
const [form, setForm] = useState({
date: "2026-09-08",
description: "",
category: categories[0]?.name ?? "Other",
amount: "",
type: "expense",
});
The important idea is that these inputs are controlled. Their value comes from form, and their onChange handler writes the latest value back into that same object.
For example, the description field should follow this pattern:
<input
value={form.description}
onChange={(event) =>
setForm((current) => ({
...current,
description: event.target.value,
}))
}
/>
Here is what each part does:
value={form.description}makes React state the source of truth for the field.event.target.valueis the text currently in the input....currentpreserves the other form fields.description: ...replaces only the description value.- The functional
setFormform uses the latest state value.
Now make the container a real HTML form. This gives the browser one standard submission event for both clicking the button and pressing Enter:
<form
onSubmit={(event) => {
event.preventDefault();
handleAddTransaction();
}}
>
{/* existing controls */}
</form>
preventDefault() stops the browser’s normal form submission, which would otherwise reload or navigate the page. The call to handleAddTransaction() starts the application’s own transaction workflow instead.
Make the add control a submit button:
<button type="submit">
<Plus size={16} />
</button>
The form now has one submission path, which is easier to extend later when the same form also supports editing.
Test it
Type into the description and amount fields. Switch between expense and income and confirm the form updates without a page reload.
Press Enter from the description field. It should use the same submit handler as the Add button.
Checkpoint
The entry form has one React state object, every field is controlled by that state, and clicking add or pressing Enter uses the same submission path.