Search code examples
javascriptreactjsreduxreact-reduxredux-reducers

Uncaught Invariant Violation on saving to redux store second time


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.


Solution

  • 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 :)