Ошибка: сбой инварианта: была обнаружена мутация состояния между отправлениями в пути ’emailReducer.email.0′

#redux #redux-toolkit

#сокращение #redux-toolkit

Вопрос:

Я получаю это сообщение об ошибке об изменении состояния, но целью Redux Toolkit является изменение состояния, поэтому я в замешательстве…

Ошибка возникает из addNewEmail -за того, что я добавляю новые электронные письма в массив, вызывающий prevEmails using useSelector , а второй параметр является обычной строкой.

 import { createSlice } from "@reduxjs/toolkit";
import { AppThunk } from "./store";

const initialState = {
   emails: [],
};

export const emailSlice = createSlice({
   name: "email",
   initialState,
   reducers: {
      setEmails: (state, action: any) => {
         state.emails = action.payload;
      },
   },
});

export const { setEmails } = emailSlice.actions;

export const addNewEmail = (prevEmails: any, email: string): AppThunk => (
   dispatch
) => {
   const allEmails = prevEmails.push(email);
   dispatch(setEmails(allEmails));
};

export default emailSlice.reducer;

export const selectEmails = (state: any) => state.emailReducer.emails;
  

Ответ №1:

Я также получал ту же ошибку, это не то, как вы выполняете действие. Все, что вам нужно, это передать это промежуточное ПО в вашем хранилище.

 const store = configureStore({
          reducer,
          middleware: (getDefaultMiddleware) => getDefaultMiddleware({
               immutableCheck: false,
               serializableCheck: false,
          })
})
  

Комментарии:

1. Это может помочь людям, которые обновляют свое существующее приложение redux до redux-toolkit.

2. Как я! Я потратил много времени, пытаясь понять, почему я получаю неизменяемую ошибку, спасибо immutableCheck: false исправлено для меня.

3. Спасатель жизни. Это именно то, что нужно проекту. Спасибо!

Ответ №2:

Как сказал @asaf-aviv, реальная проблема заключается в том, что вы пытаетесь изменить то, что есть на самом деле state.emails , за пределами редуктора:

    const allEmails = prevEmails.push(email);
   dispatch(setEmails(allEmails));
  

Вторая проблема носит концептуальный характер. Вы должны моделировать действия как «события», а не «установщики», и вкладывать как можно больше логики в редукторы. Если вы будете следовать этим рекомендациям, эта проблема не возникнет в первую очередь.

Кроме того, это даже не обязательно должно быть ошибкой — просто отправьте действие, содержащее новый объект электронной почты.

Правильный способ справиться с этим:

 export const emailSlice = createSlice({
   name: "email",
   initialState,
   reducers: {
      emailAdded: (state, action: PayloadAction<Email>) => {
         state.emails.push(action.payload)
      },
   },
});

export const { emailAdded } = emailSlice.actions;


// later
dispatch(emailAdded(newEmail));
  

Ответ №3:

Вы изменяете состояние перед отправкой действия, вы можете выполнять мутации внутри редуктора, но не за его пределами.

Вы можете изменить, prevEmails.push(email) чтобы prevEmails.concat(email) вернуть новый массив, который затем можно отправить в качестве полезной нагрузки.