Lijomon C John
Lijomon C John

Reputation: 131

How to handle individual checkbox in Reactjs

one of my application section allows users to select mu;tiple options by selecting individual checkboxes in React by populating the Item to checkboxes. I wrote a code to handle onChange of the check box to send the _id to backend API.

The problem I'm facing when clicking one checkbox all checkboxes are getting selected. I need the app to able to check one checkbox at a time and capture its key id.

my code is;

const fetchCategory = async () => {
    fetch(`http://localhost:4000/api/v1/category`)
    .then(response => response.json())
    .then(response => {
    console.log("response: ", response.categories);
    if (response.success === true) {
        setCategoryList(response.categories)
        // setIsLoading(false)
    } else {
        alert(response.message)
    }
},
(error) => {
    alert('Fetch faied: ' + error)
})
}

const [checked, setChecked] = useState(false);

const chechboxClickHandler = (id, event) => {
    setChecked(!checked)
    console.log(event);

    if (!checked) {
        console.log(!checked);
        console.log("category id: ", id);
    }        
}

return (
    <div className="card">
        <div className="card-body">
            <div className="row">
               {categoryList && categoryList.map(c => (
                   <React.Fragment>
                       <div className="col-md-3 d-flex align-items-center">
                           <div class="form-check card">
                               <img src={`http://localhost:4000/api/v1/category/icon/${c.icon}`} width="50" height="50" alt={c.icon} />
                               <input class="form-check-input" type="checkbox" name="exampleRadios" id="exampleRadios1" value="option1" checked={checked} onChange={(event) => chechboxClickHandler(c._id, event)} />
                                <label class="form-check-label" for="exampleRadios1">
                                            {c.title}
                                </label>
                            </div>
                       </div>
                   </React.Fragment>
                 ))}
            </div>
        </div>
    </div>
)

Upvotes: 0

Views: 313

Answers (1)

Pirhan
Pirhan

Reputation: 186

The problem is that you have an array of categories, but you hold a singular boolean for all of the checkboxes in state. It may look like you have multiple checkboxes, but you only have one boolean that represents the clicked state of all of them. Depending on the approach you want to take, you can add a isChecked attribute with the categories, or can hold an array that would hold the ids of the selected categories. I would recommend holding an additional array that holds the ids of the selected categories, because it may be not optimal to manipulate the categories.


New State:

const [checked, setChecked] = useState([]);

Push the id of selected category to the checked array

const chechboxClickHandler = (id, event) => {
    const cpyChecked = [...checked];

    const indexOfId = cpyChecked.indexOf(id);
    if(indexOfId === -1) {
        cpyChecked.push(id);
    }
    else {
        cpyChecked.splice(indexOfId, 1);
    }

    setChecked(cpyChecked);     
}

Render:

<div class="form-check card">
                               <img src={`http://localhost:4000/api/v1/category/icon/${c.icon}`} width="50" height="50" alt={c.icon} />
                               <input class="form-check-input" type="checkbox" name="exampleRadios" id="exampleRadios1" value="option1" checked={checked.includes(c._id)} onChange={(event) => chechboxClickHandler(c._id, event)} />
                                <label class="form-check-label" for="exampleRadios1">
                                            {c.title}
                                </label>
                            </div>

Upvotes: 1

Related Questions