I am on the newer side of React and trying to change the state of an object in an array. Currently, I am pulling the object out of the array, changing the property in that object, then adding the new object to the state again. Problem being that it sends the object to the back of the list and reorders my checkbox inputs.
const handleChange = (e) => {
if (e.target.type === "checkbox") {
// Get the role from the current state
const roleToChange = input.roles.find(
(role) => Number(role.id) === Number(e.target.id)
);
// Change checked state to opposite of current state
const changedRole = { ...roleToChange, checked: !roleToChange.checked };
// Get every role except the one that was changed
const newRoles = input.roles.filter(
(role) => Number(role.id) !== Number(e.target.id)
);
// Update the role in the state
setInput((prevState) => {
return { ...prevState, roles: [...newRoles, changedRole] };
});
}
Can I update the object in the array in-place so this doesn't happen?
CodePudding user response:
Don't .filter
- .map
instead, and return the changed object in case the ID matches, so the new object gets put at the same place in the new array as it was originally.
const handleChange = (e) => {
if (e.target.type !== "checkbox") {
return;
};
const newRoles = input.roles.map((role) =>
Number(role.id) !== Number(e.target.id)
? role
: { ...role, checked: !role.checked }
);
setInput((prevState) => {
return {
...prevState,
roles: newRoles
};
});
}
Unless the state is updated synchronously before this, which sounds a bit unlikely (but not impossible), you can also probably use setInput({ ...input, roles: newRules })
instead of the callback.