Как перестать мутировать state?

У меня state.items — объект с ключами, которые идут как id, через allIds я нахожу все элементы id, которым нужно изменить дату, но мой action в редюсере меняет сразу дату всем элементам, видимо это связано с мутабельностью и я не знаю, как это исправить... Буду очень благодарен за помощь!

const allIds = getSubTasksId(Object.values(state.items), payload.id);
allIds.map((id) => (state.items[id].date.current = payload.date));
return {
  ...state,
  items: { ...state.items },
};

Ответы (2 шт):

Автор решения: Armen

это по идее для redux? давно сним не работал, но вроде эти две вариации должны норм работать.

const objKeys = [1, 2];

let obj = {
  0: {
    title: "a",
    id: 0,
  },
  1: {
    title: "b",
    id: 1,
  },
  2: {
    title: "c",
    id: 2,
  },
};

    let newObj1 = {...obj};
    objKeys.forEach((id) => {
      newObj1 = {
        ...newObj1,
        [id]: {
          ...newObj1[id],
          title: "xyz",
        },
      };
    });
    const newObj2 = Object.fromEntries(
      Object.entries(obj).map((arr) => {
        if (objKeys.includes(+arr[0])) {
          return [
            arr[0],
            {
              ...arr[1],
              title: "ttt",
            },
          ];
        }
        return arr;
      })
    );

    console.log({ newObj2 });
    console.log({ newObj1 });

→ Ссылка
Автор решения: Sire IMPACTUS

Если ты обязательно хочешь использовать Redux и не переходить на ReduxToolkit, то поправить это можно только на стороне компонентов. Оберни каждый компонент в React.memo и вторым параметров передай функцию.

const MyComponent = (props) => <div>{props.a}</div>;
const MyMemoComponent = React.memo(MyComponent, (next, prev) => next.a === prev.a)); 

Если функция вернет true, то ререндера не будет, иначе начнется ререндер. Для более сложных объектов (где надо сравнить массивы и т.п.), пиши либо руками, либо использова lodash - _.isEqual.

→ Ссылка