React Js And Crud Checkbox Expected State Behaviour Enter a brief summary for this post

React JS Expected State Behaviour with CRUD Checkboxes

I encountered an issue recently with checkboxes in a React JS form. Apparently, there is a slight difference in what event handlers you should use. When it comes to creating a new row of data you must use an onChange event handler and when updating a row of data, you use the onClick event handler.

Why? Well, if you use the onChange event handler on the update the state isn't maintained. I see this when I coded a component and the checkbox was originally checked (active) but when unchecked (inactive) and updated on the server, the database row still had the status of being active.

On closer inspection I had to check the checkbox twice before the actual state changed (from being active to unactive).

I'm currently learning the ins and outs of React JS and this behaviour was unexpected. Out of frustration I swapped out the event handler on the update row component to the onClick one and the behaviour returned to how it should be: unchecking the checkbox (being active) resulted in the row of data in the database being inactive.

// ...
const changeValue = (field, val) => {
        const newData = { ...data };
        newData[field] = val;
        setData(newData);
    };

    const changeActive = () => {
        const newData = { ...data };
        newData["active"] = !data.active;
        setData(newData);
    };

// ...

return (
        <>
            <h5 className="card-title">Categories :: New Category</h5>
            <div>
                <Link className="btn btn-outline-dark btn-md w-25" role="button" to="/dashboard/categories">Go Back</Link>
            </div>

            <hr />
            <div className="container">
                <div className="row">
                    <div className="col-lg-8">
            
                        <form onSubmit={validateSubmit}>
                            <div className="form-group">
                                <label htmlFor="name">Name</label>
                                <input
                                    id="name"
                                    type="text"
                                    name="name"
                                    value={data.name ?? ""}
                                    className="form-control form-control-lg"
                                    placeholder="Enter a new category name"
                                    onChange={(e) => changeValue("name", e.target.value)}
                                />
                            </div>

                            <div className="form-group form-check">
                                <input 
                                    className="form-check-input" 
                                    type="checkbox" 
                                    value="" 
                                    id="active" 
                                    checked={data.active}
                                    onChange={(e) => changeActive()}
                                />
                                <label htmlFor="active">Active, yes or no?</label>
                            </div>

                            <button className="btn btn-outline-dark w-25" type="submit">Go</button>
                        </form>

                    </div>
                    <div className="col-lg-4">
            
                    </div>
                </div>
            </div>
            <hr />
        </>
    );  

That's the component above to create a row of data and the update is below.

const changeValue = (field, val) => { 
        const newData = { ...data };
        newData[field] = val;
        setData(newData);
    };

    const changeActive = () => { 
        const newData = { ...data };
        newData["active"] = !data.active;
        setData(newData);
    };

// ...

return (
		 <>
            <h5 className="card-title">Dashboard :: Edit Category</h5>
            <div className="d-flex justify-content-start">
                <Link className="btn btn-outline-dark btn-md w-25" to="/dashboard/categories">Go Back</Link>
            </div>
            <hr />
            <div className="container">
                <div className="row">
                        
                            <div className="col-lg-8">

                        <form onSubmit={validateSubmit}>
                            <div className="form-group">
                                <label htmlFor="name">Name</label>
                                <input
                                    id="name"
                                    type="text"
                                    name="name"
                                    value={data.name ?? ""}
                                    className="form-control form-control-lg"
                                    placeholder="Enter a new category name"
                                    onChange={(e) => changeValue("name", e.target.value)}
                                />
                            </div>

                            <div className="form-group form-check">
                                <input 
                                    className="form-check-input" 
                                    type="checkbox" 
                                    value="" 
                                    id="active" 
                                    defaultChecked={data.active}
                                    onClick={(e) => changeActive()}                                    
                                />
                                <label htmlFor="active">Active, yes or no?</label>
                            </div>

                            <button className="btn btn-outline-dark w-25" type="submit">Go</button>
                        </form>

                    </div>
                    <div className="col-lg-4">
            
                    </div>
                </div>
            </div>
            <hr />
		</>
	);

After a few hours head scratching things are back to normal. From now on I'll know better to not use onChange on the update part of a dashboard's CRUD. If you are starting out on the React JS learning journey hopefully this'll help you too.