简体   繁体   中英

I am getting mutation of state error between dispatches from redux

i am getting the following error:

A state mutation was detected between dispatches, in the path 'notifications.adhans.AsrAdhan'. This may cause incorrect behavior. ( https://redux.js.org/style-guide/style-guide#do-not-mutate-state )]

Following is my notifications reducer in notifications.ts file.

  import {
  RESTORE_NOTIFICATIONS,
  SET_ADHAN,
  SET_ADHANTOGGLE,
  SET_REMINDER,
  SET_REMINDERTOGGLE,
} from "./../constants";

export const initialState = {
  reminderToggle: true,
  adhanToggle: true,
  adhans: {
    FajrAdhan: false,
    DhuhrAdhan: true,
    AsrAdhan: false,  //--->getting mutation error for this
    MaghribAdhan: true,
    IshaAdhan: true,
  },
  reminders: {
    FajrReminder: false,
    DhuhrReminder: false,
    AsrReminder: true,
    MaghribReminder: false,
    IshaReminder: true,
    SunriseReminder: true,
    MidnightReminder: false,
  },
};

export default (state = initialState, action: AnyAction): notificationsT => {
  switch (action.type) {
    case SET_REMINDERTOGGLE:
      return {
        ...state,
        reminderToggle: action.payload,
      };
    case SET_ADHANTOGGLE:
      return {
        ...state,
        adhanToggle: action.payload,
      };
    case SET_ADHAN:
      return {
        ...state,
        adhans: {
          ...state.adhans,
          [action.payload.key]: action.payload.value,
        },
      };
    case SET_REMINDER:
      return {
        ...state,
        reminders: {
          ...state.reminders,
          [action.payload.key]: action.payload.value,
        },
      };

    case RESTORE_NOTIFICATIONS:
      return { ...action.payload };  

    default:
      return state;
  }
};

error stack points at src\screens\Home.tsx:127:14 in RestoreState.

Following is the relevant code for Home.tsx

import AsyncStorage from "@react-native-async-storage/async-storage";
import * as actionTypes from "../store/constants";
import { initialState as notifInitState } from "../store/reducers/notifications";
...

 const updatedNotificationsstate = { ...notifInitState };
 const adhanKeys = Object.keys(notifInitState.adhans);
 
const keysArray = [
       ...adhanKeys,
      ...//other state keys
];

 const Home = ({ navigation }) => {
  const dispatch = useAppDispatch();

  //When component mounts on start, Restore the redux state
  React.useEffect(() => {
    const RestoreState = async () => {

         const savedState = await AsyncStorage.multiGet(keysArray);
         
         savedState.forEach(([key, value]) => {
         ...
         
         if(value){

          //notifications
          if (adhanKeys.includes(key))
            return (updatedNotificationsstate.adhans[key] = JSON.parse(value));

          
          ...
        }
      });

      dispatch({
        type: actionTypes.RESTORE_NOTIFICATIONS,
        payload: updatedNotificationsstate,
      });

      
    };
    RestoreState();
    
  }, []);

  ---

  return (
    <Layout>
    ..
    </Layout>
  );
};

export default Home;

what am i doing wrong here???

Please note I have removed typesrcipt types for javascript coders convenience.

updatedNotificationsstate.adhans[key] = JSON.parse(value) looks to be a mutation.

You've correctly created a shallow copy of updatedNotificationsstate but all the elements are still references to the originals in state, ie updatedNotificationsstate.adhans is a reference to the previous state. You must also shallow copy any nested state properties that are being updated.

if (adhanKeys.includes(key)) {
  return (updatedNotificationsstate.adhans = { // <-- new object reference                            
    ...updatedNotificationsstate.adhans,       // <-- shallow copy previous
    [key]: JSON.parse(value)                   // <-- update property
  });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM