HomeGuidesReactReact Forms — Controlled Components, onChange & Form Submission
⚛️ React

React Forms and Event Handling

React forms are fundamental and frequently tested. Here's the controlled vs uncontrolled distinction and everything around form handling.

Examifyr·2026·5 min read

Controlled vs uncontrolled inputs

In controlled inputs, React state is the source of truth. In uncontrolled inputs, the DOM manages its own state.

// Controlled input: value driven by state
function ControlledForm() {
    const [email, setEmail] = useState('');

    return (
        <input
            type="email"
            value={email}                      // state is source of truth
            onChange={e => setEmail(e.target.value)}
        />
    );
}

// Uncontrolled input: DOM manages its own state
function UncontrolledForm() {
    const inputRef = useRef(null);

    const handleSubmit = () => {
        console.log(inputRef.current.value);   // read on demand
    };

    return <input ref={inputRef} type="email" />;
}
Note: Prefer controlled inputs — React state is the single source of truth, making validation and synchronisation straightforward.

Form with multiple fields

Handle multiple inputs with a single onChange handler using the input's name attribute.

function SignupForm() {
    const [form, setForm] = useState({
        name: '',
        email: '',
        password: '',
    });

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

    const handleSubmit = (e) => {
        e.preventDefault();   // prevent page reload
        console.log(form);
    };

    return (
        <form onSubmit={handleSubmit}>
            <input name="name"     value={form.name}     onChange={handleChange} />
            <input name="email"    value={form.email}    onChange={handleChange} />
            <input name="password" value={form.password} onChange={handleChange} type="password" />
            <button type="submit">Sign up</button>
        </form>
    );
}

Event handling patterns

React event handlers receive synthetic events that wrap browser events.

function EventExamples() {
    // Passing additional data to handler
    const handleItemClick = (id) => (e) => {
        e.preventDefault();
        console.log('clicked item', id);
    };

    return (
        <div>
            {/* Inline arrow function */}
            <button onClick={() => handleAction()}>Click</button>

            {/* Pass reference (better performance) */}
            <button onClick={handleAction}>Click</button>

            {/* With argument — needs wrapper */}
            <button onClick={() => handleItemClick(42)}>Click</button>

            {/* Curried handler */}
            <a href="#" onClick={handleItemClick(42)}>Item</a>
        </div>
    );
}

Exam tip

"What's a controlled component?" is a guaranteed React interview question. The answer: a form element whose value is driven by React state, with an onChange handler to update that state. The component "controls" the input.

🎯

Think you're ready? Prove it.

Take the free React readiness test. Get a score, topic breakdown, and your exact weak areas.

Take the free React test →

Free · No sign-up · Instant results

← Previous
React Conditional Rendering & Lists — &&, Ternary, and key Prop
Next →
React Component Lifecycle — Mount, Update, Unmount & Re-render Rules
← All React guides