How to Handle Forms in React with Validation

How to Handle Forms in React with Validation

How to Handle Forms in React with Validation

Controlled components give you full control over form state and make validation straightforward.

Step 1 — Set Up Form State

import { useState } from 'react';

const initialState = { name: '', email: '', message: '' };

function ContactForm() {
    const [fields, setFields]   = useState(initialState);
    const [errors, setErrors]   = useState({});
    const [success, setSuccess] = useState(false);

Step 2 — Validate the Fields

    function validate(data) {
        const errs = {};
        if (!data.name.trim())
            errs.name = 'Name is required.';
        if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email))
            errs.email = 'Enter a valid email address.';
        if (data.message.trim().length < 10)
            errs.message = 'Message must be at least 10 characters.';
        return errs;
    }

Step 3 — Handle Change and Submit

    function handleChange(e) {
        setFields(prev => ({ ...prev, [e.target.name]: e.target.value }));
    }

    async function handleSubmit(e) {
        e.preventDefault();
        const errs = validate(fields);
        if (Object.keys(errs).length) { setErrors(errs); return; }

        await fetch('/api/contact', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(fields),
        });

        setFields(initialState);
        setErrors({});
        setSuccess(true);
    }

Step 4 — Render the Form

    return (
        <form onSubmit={handleSubmit}>
            <input name="name" value={fields.name} onChange={handleChange} placeholder="Name" />
            {errors.name && <p className="error">{errors.name}</p>}

            <input name="email" value={fields.email} onChange={handleChange} placeholder="Email" />
            {errors.email && <p className="error">{errors.email}</p>}

            <textarea name="message" value={fields.message} onChange={handleChange} />
            {errors.message && <p className="error">{errors.message}</p>}

            <button type="submit">Send</button>
            {success && <p>Message sent!</p>}
        </form>
    );
}
All Comments