Nothing here
Nothing here

Reputation: 2363

Updating an object property within an array of objects in React

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?

Upvotes: 0

Views: 1728

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370659

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.

Upvotes: 4

Related Questions