Click, Fetch, Update
Sprout's "Add plant" form looks simple. Behind it, the browser must notice the submit, send the plant to the server, wait, check the answer, and only then change what the user sees. Skip the checking step and the screen can cheerfully show a plant that was never saved.
The rule
Listen, send, check, update.
Every interaction that talks to a server has these four beats:
form.addEventListener('submit', async (event) => {
event.preventDefault(); // listen
const res = await fetch('/api/plants', { // send
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: nameInput.value, water_every_days: Number(daysInput.value) }),
});
if (!res.ok) { // check
message.textContent = `Could not save (error ${res.status}).`;
return;
}
const plant = await res.json(); // update
list.append(renderPlant(plant));
});- Listen. The handler runs on
submit.event.preventDefault()stops the browser's old-style form submission, which would reload the whole page. - Send.
fetchtakes a method, headers and a body.JSON.stringifyturns the object into text, andContent-Type: application/jsontells the server how to read it. - Check.
fetchonly fails outright when no response arrives at all, such as when the network is down. A400or500still counts as a response, so you must look atres.ok, which is true only for statuses from 200 to 299. (A real app also wraps the call intry/catchto handle the network failing.) - Update. Change the page using the server's version of the plant. It carries the
idthe database just assigned, which later edits and deletes need.
One more guard is worth the two lines it costs: disable the Add button when the request leaves and enable it again when the answer arrives. Otherwise an impatient double-click sends two POSTs, and Asha ends up with two identical Basils.
The shortcut
Read any interaction code and name its four beats. A missing beat is the bug. No check: failures are silent. Update before send with no way back: the screen can lie. No preventDefault: the page reloads and your code is cut off.
Listen
Asha types "Basil" and 2, and presses Add. The submit handler runs, and
preventDefaultkeeps the page in place.
Drills
Answer fast — trust the rule.
The server answers 500. What does fetch do?
The submit handler forgets event.preventDefault(). What happens?
Why build the new list item from the response rather than from the typed values?
Which header tells Sprout's server that the request body is JSON?
Remember
- Listen, send, check, update.
- Shortcut: name the four beats in any handler; a missing beat is the bug.
- Trap: trusting
fetchto fail on errors. It only fails when no response arrives, so always checkres.ok.
