Reputation: 788
I am working on a checkbox component in React that is created from fetching group data from an API and then making a checkbox for each group. When you click a checkbox, I have set up the code to enter that specific group's ID into state in an array to be submitted with a form. My question has 2 parts. When i click a checkbox and unclick it, it enters the ID into state twice instead of removing the ID. How can I fix this?? Also, when I submit the form it is attached to I would like for the checkboxes to reset and basically unclick themselves and reset state to empty. How can i achieve this??
Here is my code:
import React, { useState, useEffect, useContext } from "react";
import { LoggedInContext } from "./contexts/LoggedIn";
import styles from "./styles/GroupCheckboxStyles";
import { withStyles } from "@material-ui/core";
function GroupCheckbox(props) {
const [groups, setGroups] = useState([]);
const [loading, setLoading] = useState(true);
const { token } = useContext(LoggedInContext);
const { classes } = props;
useEffect(() => {
fetch(process.env.REACT_APP_SERVER + "groups", {
headers: {
"Content-Type": "application/json",
Token: token
}
})
.then(res => res.json())
.then(data => {
setGroups(data.data);
setLoading(false);
});
}, [token]);
return (
<div className={classes.root} style={{ margin: `${props.margin}` }}>
<div className={classes.group_header}>Groups</div>
{loading ? (
<h1>Loading...</h1>
) : (
groups.map(x => {
return (
<div className={classes.specific_group} key={x._id}>
<input
type="checkbox"
id={x._id}
name={x.name}
onChange={props.handleGroupCheckboxClick}
/>
<label htmlFor={x.name}>{x.name}</label>
</div>
);
})
)}
</div>
);
}
export default withStyles(styles)(GroupCheckbox);
And here is from the parent component passing down to it:
const handleGroupCheckboxClick = event => {
let checkId = event.target.id;
setSelectedGroups([...selectedGroups, checkId]);
console.log(selectedGroups);
};
<GroupCheckbox
className={classes.checkbox}
handleGroupCheckboxClick={handleGroupCheckboxClick}
margin={"0 auto"}
/>
Here is an image of the checkbox component with it's log of state after clicking multiple times:
Upvotes: 1
Views: 2254
Reputation: 4268
Its easier with an object.
Change useState
from array to object
...
const [selectedGroups, setSelectedGroups] = useState({});
...
Update handler
...
const handleGroupCheckboxClick = ({ target: { id }})=> {
setSelectedGroups((s) => ({ ...s, [id]: !s[id] }));
};
...
Then you can filter all true keys when submitting.
const keys = Object.keys(selectedGroups);
const arrayOfIds = [];
for(let i = 0; i<keys.length; i++) {
const id = keys[i];
if(selectedGroups[id]) arrayOfIds.push(id);
}
console.log({ arrayOfIds });
You can also connect the object to the checkboxes. When the object is renewed with a empty object, all checkboxes will be reset.
Upvotes: 2