I have a below function which takes in a response and transforms/adds properties to a response object for my UI and the transformed response is again returned.
So the way it works is initially the method is called with no existing data and it works fine.
However when I do result = data;…where data is actually existing data that was saved to Redux state and then when mutations are run on that existing data. At that point, I get the issue (TypeError: Cannot assign to read only property ‘secGroupOrder’ of object ‘#’ ) after having the transformed response go through Redux Toolkit states. So the error does not come for the first run, but for subsequent runs. This error is even after setting writable to true on all the properties. Not sure what can I do to fix this ?
Below is my function
function formatData(initialResponse, existing) {
let response = {};
Object.defineProperties(response, {
secGroupOrder: {writable: true},
secGroups: {writable: true},
sections: {writable: true},
fields: {writable: true}
});
if (existing) {
response = existing;
let newOrder = copySecGroupOrder(secGroupOrder);
newOrder.forEach(group => {
let existingGroup = existing.secGroups[group.name];
if (existingGroup && existingGroup.sections) {
group.sections = existingGroup.sections;
}
});
response.secGroupOrder = newOrder;
//response = Object.assign({}, response , secGroupOrder, newOrder); // Commented above and replaced since it was giving "Cannot assign to read only property" error
} else {
response = {
secGroupOrder: copySecGroupOrder(secGroupOrder),
secGroups: {},
sections: sections,
fields: copyFields(fields)
};
}
response.secGroupOrder.forEach(group => {
response.secGroups[group.name] = group;
if (!group.sections) {
group.sections = {};
}
});
if( response.secGroups['Comp 1']){
response.secGroups['Comp 1'].component = Cmp1;
}
if (response.secGroups['Comp 2']) {
response.secGroups['Comp 2'].component = Cmp2;
}
return response;
}
3
Answers
Your code here is directly modifying your Redux Toolkit state, but outside of a reducer.
You are not creating "copies" by doing
response = existing;
– it’s just another variable name pointing to the state you have in Redux – and Redux state is not allowed to be modified.So, your line
is equal to
If you want to directly modify those values, you have to make sure to make a deep copy first.
I think you’re facing this issue because you’re trying to change the data stored in your store’s state directly without going through a reducer, look into shallow and deep copies in javascript.
Essentially your issue can be solved if you make a deep copy of your object, since making changes to the deep copy will not cause store to throw you an error
I would recommend using reducers to make any changes to existing states, that is the preferred approach. If for some reason you don’t wish to do that and only use reducers to do a simple
and not do anything else in reducer (though would recommend making any changes you do in a reducer), you can make a deep copy, and pass it to the reducer after you’re done.
You can look into deep and shallow copies here.
https://www.freecodecamp.org/news/copying-stuff-in-javascript-how-to-differentiate-between-deep-and-shallow-copies-b6d8c1ef09cd/
Make a deep copy of
existing
withstructuredClone
to avoid modifying it: