[英]Material-table TypeError: Cannot add property tableData, object is not extensible
I'm using meterial-table
with React
.我正在使用带有
React
meterial-table
。 I'm trying to assign data from an array coming from an api like this我正在尝试从来自这样的 api 的数组中分配数据
<MaterialTable
columns={columns}
data={rows}
...
/>
Where columns
and rows
are api data.其中
columns
和rows
是 api 数据。 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
或在后台使用immer
的库(例如@reduxjs/toolkit
)。 immer
uses Object.freeze
to make the objects it produces immutable. immer
使用Object.freeze
使其生成的对象不可变。
material-table
modifies its own props (which is a very ugly antipattern). material-table
修改了自己的 props(这是一个非常丑陋的反模式)。 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).找到一种在 immer 实例中禁用冻结的方法(查看 API 文档,了解您认为可能冻结了您的状态的任何内容)。
Override Object.freeze
making it do nothing (very hacky, should be avoided - and yet it might be your best shot here):覆盖
Object.freeze
使其什么都不做(非常hacky,应该避免 - 但它可能是你最好的选择):
window.Object.freeze = function(obj) { return obj }
MaterialTable
.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
.这与
material-table
或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.这很可能与您的 api 响应有关,出于某种原因在其上应用了
Object.preventExtensions()
,也许这是Axios
行为。 So when material-table
is trying to add an id
field to each object, it's facing this error.因此,当
material-table
尝试为每个对象添加一个id
字段时,它会遇到此错误。 Although not optimal, try to copy your api data to a new array of objects so material-table
can modify them, eg:虽然不是最佳的,但尝试将您的 api 数据复制到一个新的对象数组中,以便
material-table
可以修改它们,例如:
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请注意,我没有使用
rows.map(o => o)
因为这将复制具有相同对象引用的数组
EDIT : It's worth mentioning that using spread operator or Object.assign will only give a shallow copy, ie will not copy nested objects.编辑:值得一提的是,使用扩展运算符或Object.assign只会给出浅拷贝,即不会复制嵌套对象。 One work-around for this is to use
JSON.parse(JSON.stringify(object))
.一种解决方法是使用
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?请注意,这会导致一些数据丢失,其他替代方法在这个答案上: What is the most effective way to deep clone an object in JavaScript?
import { setAutoFreeze } from 'immer';从“immer”导入 { setAutoFreeze }; setAutoFreeze(false);
设置自动冻结(假);
worked for me.为我工作。 material table should consider an api that plays well with immer
材质表应该考虑一个和immer配合得很好的api
I got this error while passing the array data in the Material Data Table
I was using reduxjs/toolkit
在我使用
reduxjs/toolkit
的Material Data Table
中传递数组数据时出现此错误
As the object are not modifiable ,due to internal implementation of Object.freeze()
by由于对象是不可修改的,由于
Object.freeze()
的内部实现
reduxjs/toolkit reduxjs/工具包
const {cycleList}=JSON.parse(JSON.stringify(useSelector(state=>state.cycleSlice)));
I used above method to create a new copy of the object.我使用上述方法来创建对象的新副本。
In my case Using "structuredClone" function solved this same issue.就我而言,使用“structuredClone”功能解决了同样的问题。
var a = useSelector((state) =>state.cusLocChartTable.CusLocationCT);
const cloneData = structuredClone(a.billcity_table);
<ThemeProvider theme={defaultMaterialTheme}>
<MaterialTable
columns={[
{ title: 'City', field: 'city' },
{ title: 'Customers', field: 'customers' }
]}
data={cloneData}
title="Customers"
/>
</ThemeProvider>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.