Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Redux: A state mutation was detected inside a dispatch

I realise there are probably a million and one different causes for this error but I am struggling to find the cause of mine. I am relatively new to Redux and state handling in the Reducer and have learned from a few examples online to come up with the code sample below which is called within the Reducer:

const updateTripsWhereVenueDeleted = (state, action) => {
  debugger;
  const deletedVenueId = action.venue.Id;
  const originalTrips = [...state];

  const newTrips = originalTrips.map((trip) => {
    if (trip.VenueId === deletedVenueId) {
      trip.VenueId = 0;
      trip.VenuePegId = 0;
    }
    return trip;
  });
  debugger;
  return [...newTrips];
};

I have state which is an array of Trips:

enter image description here

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

And Action contains a ‘Venue’ record.
Basically, the Venue being passed was deleted and I want to update the relevant fields on all Trips that reference the deleted Venue.

When I run the above code in the Reducer things seem to go in the right direction until the browser crashes with the following error:

Unhandled Rejection (Invariant Violation): A state mutation was
detected inside a dispatch, in the path: trips.0.VenueId. Take a
look at the reducer(s) handling the action
{"type":"UPDATE_TRIPS_VENUE_DELETED","venue": {…. the object}

UPDATE_TRIPS_VENUE_DELETED is the action.type that calls my method above.

Is there an obvious mis-use of handling (spread) arrays in a state or something. I feel this should be an easy thing to do but nothing I have tried has so far worked correctly.

>Solution :

Spreading an object or array ([...state] here) does not break nested references. So you are mutating state by not making a copy of the nested object within your maptrip.VenueId = 0;.

This leads to another observation, map returns a new array, so this negates the need to use originalTrips altogether. It is just as safe to do state.map(). The final spread [...newTrips] is definitely unnecessary as well.

To fix your mutation create a clone of the objects to be updated:

const updateTripsWhereVenueDeleted = (state, action) => {

  const deletedVenueId = action.venue.Id;

  const newTrips = state.map((trip) => {
    if (trip.VenueId === deletedVenueId) {
      // Copy other trip values into NEW object and return it
      return { ...trip, VenueId: 0, VenuePegId: 0 };
    }
    // If not matched above, just return the old trip
    return trip;
  });

  return newTrips;
};
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading