I'm using meterial-table
with React
. I'm trying to assign data from an array coming from an api like this
<MaterialTable
columns={columns}
data={rows}
...
/>
Where columns
and rows
are api data. But I'm getting this error:
TypeError: Cannot add property tableData, object is not extensible
Notably When I use mock hard-coded data, things are working perfectly. After some search, I couldn't find any solution for it, any help?
You are most likely using immer
or a library that uses immer
under the hood (like @reduxjs/toolkit
). immer
uses Object.freeze
to make the objects it produces immutable.
material-table
modifies its own props (which is a very ugly antipattern). When libraries break rules, they won't work with libraries that try to enforce them.
There is no way to unfreeze an object that has been frozen, but you have a couple of options:
Find a way to disable freezing in the immer instance (check out the API docs of whatever you think might have frozen your state).
Override Object.freeze
making it do nothing (very hacky, should be avoided - and yet it might be your best shot here):
window.Object.freeze = function(obj) { return obj }
MaterialTable
. This is also far from ideal, especially if you have a lot of data.This has nothing to do with material-table
or React
. Most probably this is related to your api response having Object.preventExtensions()
applied on it for some reason, maybe this is an Axios
behavior. So when material-table
is trying to add an id
field to each object, it's facing this error.
Although not optimal, try to copy your api data to a new array of objects so material-table
can modify them, e.g:
const editable = rows.map(o => ({ ...o }));
<MaterialTable
columns={columns}
data={editable}
...
/>
Note that I didn't use
rows.map(o => o)
as this will copy the array with the same objects references
EDIT:
It's worth mentioning that using spread operator or Object.assign will only give a shallow copy, i.e. will not copy nested objects. One work-around for this is to use JSON.parse(JSON.stringify(object))
. Please note that this would cause some data loss, other alternatives are on this answer:
What is the most efficient way to deep clone an object in JavaScript?
import { setAutoFreeze } from 'immer'; setAutoFreeze(false);
worked for me. material table should consider an api that plays well with immer
I got this error while passing the array data in the Material Data Table
I was using reduxjs/toolkit
As the object are not modifiable ,due to internal implementation of Object.freeze()
by
reduxjs/toolkit
const {cycleList}=JSON.parse(JSON.stringify(useSelector(state=>state.cycleSlice)));
I used above method to create a new copy of the object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With