React.js: Forms

February 7, 2021

Table of Contents


React.js Forms

Building a form on a React.js application is not much different than building it for a regular web page. You can use the same html elements: input, textarea, select, and button.

However, you will need to add an onChange event to each of your form controls.

Additionally, you will have to keep your form's data on a state variable or object.

As shown on this example we are using the useState hook to define, and update a state object.
Also we are using an onSubmit event where we display the values of the form fields stored on the state variable.


import React, { useState } from "react";

const colors  = ['Red', 'Blue', 'Yellow', 'Purple', 'Orange', 'Green'];
const seasons = ['Spring', 'Summer', 'Autumm', 'Winter'];
const hobbies = ['Reading', 'Writing', 'Painting', 'Walking'];

function SampleForm(props) {
    const [state, setState] = useState({
        name: 'My Name',
        comments: 'My Comments',
        color: 'Blue',
        season: 'Spring',
        hobbies: [false, true, true, false]
    });

    function handleChange(event) {
        const {name, value, type} = event.target;

        if (type == 'checkbox') {
            const {checked} = event.target;

            let newValues = [...state[name]];    // Copy array with the spread operator
            newValues[value] = checked;          // Update the element that has been changed
            setState(prevState => ({...prevState, [name]: newValues}));
        } else {
            setState(prevState => ({...prevState, [name]: value}));
        }
    }

    function handleSubmit(event) {
        event.preventDefault();
        alert(JSON.stringify(state));
    }

    return (
        <form onSubmit={handleSubmit}>
            <p>
                <label>Name:</label><br/>
                <input type="text" name="name" value={state.name} onChange={handleChange}
                    size="20"
                />
            </p>

            <p>
                <label>Comments:</label><br/>
                <textarea name="comments" value={state.comments} onChange={handleChange}
                    cols="40" rows="4"
                />
            </p>

            <p>
                <span>Favorite Color</span><br/>
                <select name="color" value={state.color} onChange={handleChange}>
                    {props.colors.map((c) =>
                        <option key={c} value={c}>{c}</option>
                    )}
                </select>
            </p>

            <p>
                <span>Favorite Season</span><br/>
                {props.seasons.map((s) =>
                    <label key={s}>
                        <input type="radio" name="season" value={s} checked={state.season == s}
                            onChange={handleChange} /> {s}
                    </label>
                )}
            </p>

            <p>
                <span>Hobbies</span><br/>
                {props.hobbies.map((h, i) =>
                    <label key={i}>
                        <input type="checkbox" name="hobbies" value={i} checked={state.hobbies[i]}
                            onChange={handleChange} /> {h}
                    </label>
                )}
            </p>

            <button type="submit">Submit</button>
        </form>
    ); 
}

function App() {
    return (
        <>
            <SampleForm colors={colors} seasons={seasons} hobbies={hobbies} />
        </>
    );
}

export default App;

Live Demo

See a live demo of the above code on StackBlitz here.