Chapter 4 of 4
Submitting and Validating
Handling submit, showing validation messages, and a full working example.
Handle submission on the form's onSubmit, prevent the default reload, and read the values straight from state.
import { useState } from "react";
function SignupForm({ onSignup }) {
const [form, setForm] = useState({ email: "", password: "" });
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
function validate(values) {
const found = {};
if (!values.email.includes("@")) found.email = "Enter a valid email";
if (values.password.length < 8) found.password = "Use at least 8 characters";
return found;
}
async function handleSubmit(event) {
event.preventDefault();
const found = validate(form);
setErrors(found);
if (Object.keys(found).length > 0) return;
setIsSubmitting(true);
try {
await onSignup(form);
} finally {
setIsSubmitting(false);
}
}
function handleChange(event) {
const { name, value } = event.target;
setForm((previous) => ({ ...previous, [name]: value }));
}
return (
<form onSubmit={handleSubmit} noValidate>
<label htmlFor="email">Email</label>
<input id="email" name="email" value={form.email} onChange={handleChange} />
{errors.email && <p role="alert">{errors.email}</p>}
<label htmlFor="password">Password</label>
<input
id="password"
name="password"
type="password"
value={form.password}
onChange={handleChange}
/>
{errors.password && <p role="alert">{errors.password}</p>}
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Creating account..." : "Sign up"}
</button>
</form>
);
}Things worth copying from that example
htmlForon every label, matching the input'sid. This is what screen readers rely on.role="alert"on error messages so they are announced when they appear.disabledwhile submitting, to prevent double submissions.- A
finallyblock, so a failed request does not leave the button stuck.
Write a validation function
Complete validateEmail so it returns an error message for invalid input and an empty string for valid input.