Вопрос по react-redux, javascript, redux, reactjs – используя… распространение, но при этом редукция все еще выдает предупреждение о мутации состояния

3

Redux выдает предупреждение об отправке:

Error: A state mutation was detected inside a dispatch, in the path: 
roundHistory.2.tickets. Take a look at the reducer(s) handling the action {"type":"ARCHIVE_TICKETS","roundId":"575acd8373e574282ef18717","data":[{"_id":"575acd9573e574282ef18718","value":7,"user_id":"574c72156f355fc723ecdbbf","round_id":"575acd8373e574282ef18717","__v":0},{"_id":"575acd9573e574282ef18719","value":9,"user_id":"574c72156f355fc723ecdbbf","round_id":"575acd8373e574282ef18717","__v":0},{"_id":"575acd9573e574282ef1871a","value":8,"user_id":"574c72156f355fc723ecdbbf","round_id":"575acd8373e574282ef18717","__v":0},{"_id":"575acdac73e574282ef1871b","value":19,"user_id":"574c72156f355fc723ecdbbf","round_id":"575acd8373e574282ef18717","__v":0},{"_id":"575ad50c4c17851c12a3ec23","value":29,"user_id":"57522f0b1f08fc4257b9cbc6","round_id":"575acd8373e574282ef18717","__v":0},{"_id":"575ad50c4c17851c12a3ec24","value":28,"user_id":"57522f0b1f08fc4257b9cbc6","round_id":"575acd8373e574282ef18717","__v":0},{"_id":"575ad

Единственный редуктор обработкиARCHIVE_TICKETS это действие:

case 'ARCHIVE_TICKETS' :
  var archive = [...state.roundHistory];
  for (var i in archive) {
    if (archive[i]._id === action.roundId) {
      archive[i].tickets = action.data;
    }
  }
  return Object.assign({}, state, {
    roundHistory: archive
  });

Как это может изменить состояние, если я использую [... распространения]?

Ваш Ответ

2   ответа
11

[...state.roundHistory] здесь похоже на[].concat(state.roundHistory), Это создает новый массив, но объектыв массив совместно сstate.roundHistory, Если вы хотите изменить их, вам нужно будет сделать копии каждого элемента.

Вы можете сделать это используяObject.assignаналогично тому, что вы сделали для вашего возвращаемого значения:

var archive = state.roundHistory.map(value => Object.assign({}, value));

Или (как вы предложили в своем собственном ответе) вы можете использовать нотацию с разбросом объектов:

var archive = state.roundHistory.map(value => {...value});
Отлично! Именно то, что я понял несколько минут назад, но еще более элегантно. Syberic
0

я понял. Расширение массива объектов дает новый массив, но со ссылками на те же объекты. Чтобы избежать мутации, я добавил эту строку:archive[i] = {...state.roundHistory[i]};

case 'ARCHIVE_TICKETS' :
  var archive = [...state.roundHistory];
  for (var i in archive) {
    archive[i] = {...state.roundHistory[i]};
    if (archive[i]._id === action.roundId) {
      archive[i].tickets = action.data;
    }
  }
  return Object.assign({}, state, {
    roundHistory: archive
  });

Похожие вопросы