【问题标题】:Material-table TypeError: Cannot add property tableData, object is not extensible材料表类型错误:无法添加属性表数据,对象不可扩展
【发布时间】:2020-04-26 03:23:41
【问题描述】:

我正在使用 meterial-tableReact。我正在尝试从来自这样的 api 的数组中分配数据

<MaterialTable
  columns={columns}
  data={rows}
  ...
/>

其中columnsrows 是api 数据。但是我收到了这个错误:

TypeError: Cannot add property tableData, object is not extensible

值得注意的是,当我使用模拟硬编码数据时,一切正常。经过一番搜索,我找不到任何解决方案,有什么帮助吗?

【问题讨论】:

标签: javascript reactjs axios material-ui material-table


【解决方案1】:

您很可能使用immer 或在后台使用immer 的库(例如@reduxjs/toolkit)。 immer 使用 Object.freeze 使其生成的对象不可变。

material-table 修改自己的 props(这是一个非常丑陋的反模式)。当图书馆违反规则时,它们不会与试图强制执行规则的图书馆合作。

无法解冻已冻结的对象,但您有几个选择:

  1. 找到一种在 immer 实例中禁用冻结的方法(查看 API 文档,了解您认为可能冻结了您的状态的任何内容)。

  2. 覆盖 Object.freeze 让它什么都不做(非常hacky,应该避免 - 但它可能是你最好的选择):

window.Object.freeze = function(obj) { return obj }
  1. 在将状态传递给MaterialTable 之前克隆/深度复制您的状态。这也远非理想,尤其是在您拥有大量数据的情况下。

【讨论】:

  • 非常感谢您的建议/解释。我在使用immer 时遇到了完全相同的问题。值得庆幸的是,immer 确实提供了禁用冻结的功能:import { setAutoFreeze } from 'immer'; setAutoFreeze(false);
【解决方案2】:

这与material-tableReact 无关。这很可能与您的 api 响应有关,出于某种原因在其上应用了 Object.preventExtensions(),也许这是 Axios 行为。所以当material-table 试图向每个对象添加一个id 字段时,它就会面临这个错误。 虽然不是最佳的,但尝试将您的 api 数据复制到新的对象数组中,以便 material-table 可以修改它们,例如:

const editable = rows.map(o => ({ ...o }));
<MaterialTable
  columns={columns}
  data={editable}
  ...
/>

请注意,我没有使用rows.map(o =&gt; o),因为这将复制具有相同对象引用的数组

编辑: 值得一提的是,使用 spread operatorObject.assign 只会给出浅拷贝,即不会拷贝嵌套对象。一种解决方法是使用JSON.parse(JSON.stringify(object))。请注意,这会导致一些数据丢失,这个答案还有其他选择: What is the most efficient way to deep clone an object in JavaScript?

【讨论】:

  • 值得注意的是,如果使用这种方法,“你只会得到浅拷贝”,它可能是你想要的,也可能不是 =) 2ality.com/2016/10/…
【解决方案3】:

从 'immer' 导入 { setAutoFreeze }; setAutoFreeze(false);

为我工作。 材质表应该考虑一个和immer很好玩的api

【讨论】:

  • 谢谢。如果使用 Redux Toolkit,你怎么称呼它?
  • 您在全局范围内或在开始使用 immer 之前将 AutoFreeze 设置为 false
【解决方案4】:

Material Data Table 中传递数组数据时出现此错误 我用的是reduxjs/toolkit

由于对象不可修改,由于Object.freeze() by 的内部实现

reduxjs/工具包

 const {cycleList}=JSON.parse(JSON.stringify(useSelector(state=>state.cycleSlice))); 

我使用上述方法创建了对象的新副本。

【讨论】:

    猜你喜欢
    • 2019-02-28
    • 2017-09-19
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 2021-12-09
    • 2021-02-02
    • 1970-01-01
    • 2020-11-15
    相关资源
    最近更新 更多