1

I'm relatively new to React-Redux and was facing an issue where the if i update the state of a reducer param for the first time, it executes perfectly, then if i execute it again with some different value it throws this exception in my try/catch block :

Invariant Violation: 
A state mutation was detected between dispatches, in the path "object1.object2.0.object3.0.value"

Now I've added another update for the state whenever it catches the exception, and after the first exception, the states are updated accordingly and doesn't give any exception for any further updates.

Previously it was happening for every update call but following a few solutions online, now it only happens when the value is updated for the second time. Here is the code snippet that I'm using to update my state.


let tempObject3 = [
  
  {
    name : "param1",
    value = "",
  }
  {
    name : "param2",
    value = "",
  }
  {
    name : "param3",
    value = "",
  }

];
const component = (props) = {

 //this state variable is updated every time there is a change in the form
 const [formState, setFormState] = React.useState({
    value1 : "",
    value2 : "",
    value3 : "",
  });

  const updateState = async () = {
   const temp = async () = {
     // have used other cloning libraries like just-clone and spread operator and JSON.parse(JSON.stringify(object))
     let object2Copy = _.cloneDeep(props.object2);
     for(var i=0; i<object2Copy.length; i++)
     {
       let object2ElementCopy = _.cloneDeep(object2Copy[i]);
       if(object2ElementCopy.name === "desiredName")
       {
         //code for populating tempObject3, with modified data from formState state variable

         if('object3' in object2ElementCopy)
         {
           let object3Copy = _.cloneDeep(object2ElementCopy.object3)
           object2ElementCopy = {...object2ElementCopy, object3 : tempObject3}
         }
         else
         {
           object2ElementCopy.object3 = tempObject3;
         }
         object2Copy[i] = object2ElementCopy
       }
     }
     return object2Copy;
    }
    try 
    {
      props.updateObject2(await temp());
    }
    catch(e)
    {
      //update after which no  further exceptions are caught
      props.updateObject2(await temp());
      console.log(e);
    }
  }
}

Some methods and objects used here are passed to props via MapDispatchToProps and MapStateToProps.

The exception only arises when I update it for the second time, although the same reducer is working fine in other components without the need for async and await.

Yes i know the logic should be in the reducer but I've even tried doing that and the same exception keeps happening. I've even created a new object in the reducer to save this data to which has only one level, still it was giving me the same error.

Sampurna
  • 205
  • 2
  • 9
  • The update logic here is _really_ hard to follow. Can you show an example of what the actual state update is that you're trying to accomplish, by itself? – markerikson Dec 18 '21 at 16:23
  • Hey @markerikson i solved the error on my own and help from a few other people. Thanks anyways :) – Sampurna Dec 20 '21 at 11:13

1 Answers1

1

So anyone who will face this error in the future, let me help you not waste a lot of time, and bang your head against the table.

The problem here is that i was getting the error the second time after updating the object3 right. What was happening every time in the code was that i was using the same tempObject3 to write new values with.

Now why was it giving an error the second time? because the first time i updated it in redux, that object created a reference to the redux store, now every other time i try to update it, the same reference was used and a new tempObject3 wasn't created, hence the Invariant Violation .

So anyone who face this error or something similar, please do this before updating the value of the object again :-

tempObject3_copy = _.cloneDeep(tempObject3);

//logic for updating tempObject3Copy with new values 

// update to redux store after updating object with new values

Hope this collective effort for the solution will be helpful :)

Sampurna
  • 205
  • 2
  • 9
  • 1
    FWIW [`cloneDeep()` is almost _never_ the right answer here](https://redux.js.org/faq/performance#do-i-have-to-deep-clone-my-state-in-a-reducer-isnt-copying-my-state-going-to-be-slow). Instead, the better approach is to [put as much logic as possible in the reducer](https://redux.js.org/style-guide/style-guide#put-as-much-logic-as-possible-in-reducers), and use [our official Redux Toolkit package to write your Redux logic](https://redux.js.org/tutorials/fundamentals/part-8-modern-redux). That will simplify updates considerably and avoid bugs like this. – markerikson Dec 20 '21 at 17:52
  • Yeah, will try and make things more organised and according to the official documentation from now : ) – Sampurna Dec 21 '21 at 05:15