Unit 1 · Module 3
The Lifecycle of a Click
What happens from finger on screen to data in database
In Module 2, we said "JavaScript is what catches the click." Now let's walk through what actually happens, step by step, with everything you know — variables, functions, types, all of it working together.
A user has filled out an intake form and clicks the Submit button. Here's what JavaScript does, in order.
Step 1: The event fires
The browser is always listening. When the user clicks that button, the browser creates an event — a small object that describes what just happened.
The browser automatically creates something like this
{
type: "click",
target: submitButton,
timeStamp: 1712438400000
} That object gets handed to JavaScript. This is the starting gun.
Step 2: The event handler runs
Somewhere in your code, a developer connected a function to that button. "When this button is clicked, run this function." That connection was made when the page first loaded:
Connecting a function to a button
submitButton.addEventListener("click", handleSubmit)
Translation: "Dear browser — when someone clicks submitButton, call the function
named handleSubmit."
addEventListener is how your code communicates to the browser which events it
cares about. The browser has been holding onto that instruction since the page loaded. Now
the click happened. So it calls handleSubmit.
Step 3: The function gathers the variables
handleSubmit starts running. First thing — gather up all the data the user typed.
Those form fields have been sitting in the browser the whole time the user was filling things out:
Gathering form data into one variable
function handleSubmit() {
let formData = {
firstName: firstNameInput.value,
lastName: lastNameInput.value,
email: emailInput.value,
caseType: caseTypeDropdown.value,
phone: phoneInput.value
}
}
Every .value reads what the user typed into that field. All of those values get
bundled into one object called formData. This is the moment where individual
pieces of information get collected into one organized package.
Step 4: Validation — checking the data
Before sending anything anywhere, JavaScript checks if the data is good. This isn't type-checking — it's rule-checking. Are the required fields filled in?
Validation with conditionals
if (!formData.firstName) {
showError("First name is required")
return
}
if (!formData.email) {
showError("Email is required")
return
}
The if keyword is a conditional — a built-in JavaScript structure
that checks a condition and runs code only if that condition is true. It's not a function.
It's one of those bottom-layer built-in keywords like return and let.
The ! means "not." So !formData.firstName means "if firstName is
not present or is empty."
Step 5: The API call — sending data to the server
If validation passes, JavaScript sends the data out of the browser:
Sending data to the server
let response = await fetch("/api/lead-intake", {
method: "POST",
body: JSON.stringify(formData)
}) Let's break this one line apart — there's a lot happening:
let response— creating a variable calledresponse=— put the result of the right side into this variablefetch(...)— calling a built-in function that sends data to a serverawait— wait here until the server responds before moving on"/api/lead-intake"— the URL of the API endpoint (the route on your server)method: "POST"— the type of operation (POST means "save new data")JSON.stringify(formData)— converts the object in RAM into text the server can receive
This is the moment data leaves the browser. fetch is a built-in JavaScript
function — one of the few, like typeof. It sends an HTTP request to your server.
HTTP is the protocol — the agreed-upon format — for how browsers and servers communicate.
The http:// in URLs tells the browser "use this protocol."
Step 6: The server responds
The backend (your API route at /api/lead-intake) receives the data, saves it
to the database, and sends back a response:
Receiving the response
let result = await response.json()
The server sent back JSON. .json() converts it from text back into a JavaScript
object. Now result is a variable holding whatever the server decided to send
back — maybe { success: true, leadId: 247 }.
Step 7: The UI updates
Based on what came back, JavaScript updates what the user sees:
Updating the screen
if (result.success) {
showConfirmation("Your intake form has been submitted!")
clearForm()
} else {
showError("Something went wrong. Please try again.")
}
Another conditional. If the server said success, show a confirmation and clear the form. If
not, show an error. showConfirmation and clearForm are functions —
each one is a named set of instructions defined somewhere else.
The full function — all seven steps
handleSubmit — the complete lifecycle
async function handleSubmit() {
// Step 3: Gather variables
let formData = {
firstName: firstNameInput.value,
lastName: lastNameInput.value,
email: emailInput.value,
caseType: caseTypeDropdown.value,
phone: phoneInput.value
}
// Step 4: Validate
if (!formData.firstName) {
showError("First name is required")
return
}
if (!formData.email) {
showError("Email is required")
return
}
// Step 5: Send to server
let response = await fetch("/api/lead-intake", {
method: "POST",
body: JSON.stringify(formData)
})
// Step 6: Receive response
let result = await response.json()
// Step 7: Update UI
if (result.success) {
showConfirmation("Your intake form has been submitted!")
clearForm()
} else {
showError("Something went wrong. Please try again.")
}
}
The async keyword on the function means "this function does something that takes
time — like talking to a server — and needs to wait for responses." That's why await
appears inside it. They're a pair: async on the function, await
at the specific moments where waiting happens.
Everything from this module in one function
Every concept from Module 3 is in that function:
- Variables —
formData,response,result— named containers holding information in RAM - Functions —
handleSubmitis a function that calls other functions:showError,showConfirmation,clearForm,fetch - Types —
formDataholds an object,formData.firstNameholds a string,result.successholds a boolean - Conditionals —
ifstatements making decisions based on data - The event — a click triggered all of this
The chain of locations
Three different computers are involved in this lifecycle. The user's, the server's, and the database's.
- Browser (user's device) — JavaScript collects form data into variables, calls fetch
- Internet — HTTP message travels from user's browser to the server
- Server (Vercel's computer) — API route code runs, talks to database
- Database (Supabase's computer) — data gets saved
- Server — API route creates a response
- Internet — response travels back
- Browser — JavaScript receives response, puts it in a variable, updates the screen
That whole round trip happens in milliseconds. Every click. Every submit. Every save.