Home > Mobile >  Updating an object property within an array of objects in React
Updating an object property within an array of objects in React

Time:03-15

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.

  • Related