Client-Side Form Validation
In this page:
function validate(values) {
const errors = {};
if (!values.field) errors.field = "Error message";
return errors;
}
const errors = validate(values);
<button disabled={Object.keys(errors).length > 0}>Submit</button>
Writing a Simple Validation Function
A validation function takes the current form values and returns an object describing what's wrong, if anything. Keeping validation logic in a plain function (separate from JSX) makes it easy to test and reuse.
Example: Writing a Simple Validation Function
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function validate(email) {
if (!email) return "Email is required";
if (!email.includes("@")) return "Email must contain @";
return "";
}
function App() {
const [email, setEmail] = React.useState("");
const error = validate(email);
return <div><input value={email} onChange={e => setEmail(e.target.value)} /><p style={{color: "red"}}>{error}</p></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
Showing Errors Only After the Field Is Touched
Showing 'Email is required' before the user has even typed anything feels aggressive. Tracking a touched state per field, set to true on blur, lets you delay showing errors until the user has actually interacted with that field.
Example: Showing Errors Only After the Field Is Touched
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [email, setEmail] = React.useState("");
const [touched, setTouched] = React.useState(false);
const error = !email ? "Email is required" : "";
return (
<div>
<input value={email} onChange={e => setEmail(e.target.value)} onBlur={() => setTouched(true)} />
{touched && <p style={{color: "red"}}>{error}</p>}
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
Disabling Submit Until the Form Is Valid
A submit button's disabled prop can be tied directly to whether the form currently has errors. This gives an immediate visual signal and prevents invalid submissions entirely, rather than relying only on an error message.
Example: Disabling Submit Until the Form Is Valid
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
function App() {
const [email, setEmail] = React.useState("");
const isValid = email.includes("@");
return (
<div>
<input value={email} onChange={e => setEmail(e.target.value)} />
<button disabled={!isValid}>Submit</button>
</div>
);
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>
</body>
</html>
- Validating only on submit and never giving feedback while the user is still typing.
- Showing all error messages before the user has even touched the form.
- Not disabling the submit button when the form is invalid, letting users submit bad data anyway.
- Client-side validation checks form values against rules (required, format, length) before submission.
- Validation can run on every change, on blur, or only on submit, each with different UX tradeoffs.
- Storing an errors object alongside form state lets you show field-specific messages.
- Disabling the submit button based on validity prevents obviously-invalid submissions.
No React-version restriction — pure JavaScript validation logic works in any supported React version.
Chapter Quiz — Complete all 8 topics to unlock
0/8 topics done
Complete these topics first: