繁体   English   中英

为什么 memory 泄漏发生并在我关闭并重新打开反应组件(材料表)时渲染速度变慢?

[英]Why memory leak happend and render slowing down when I close and re-open react component (material-table)?

我有用于学习的基本反应示例,并且在我的组件之一中使用了材料表。 每次我更改页面并重新打开它(卸载和安装组件)时,我的包含材料表的组件加载得更慢。 我在下面分享我的代码。


import MaterialTable from 'material-table';

const columns = [
    { title: 'Id', field: 'id', hidden: true },
    { title: 'Username', field: 'username' },
    { title: 'Name', field: 'name' },
    { title: 'Phone', field: 'phone'}
];

const tableData = [
    {
        id: 1,
        username: "User-1",
        name: "name-1",
        phone: "555 444 33 22"
    },
    {
        id: 2,
        username: "User-2",
        name: "name-2",
        phone: "111 222 33 44"
    },
    {
        id: 3,
        username: "User-3",
        name: "name-3",
        phone: "999 999 99 99"
    }
];

const MTable = () => {
    return (
        <MaterialTable 
            title="Basic Search Preview"
            columns={columns}
            data={tableData}
            options={{search: true }}
        />
    )
}

export default MTable


经过长时间的搜索,我没有找到任何解决方案,经过长时间的尝试,我只是像下面这样更改列定义的位置。


const MTable = () => {

    const columns = [
        { title: 'Id', field: 'id', hidden: true },
        { title: 'Username', field: 'username' },
        { title: 'Name', field: 'name' },
        { title: 'Phone', field: 'phone'}
    ];

    return (
        <MaterialTable 
            title="Basic Search Preview"
            columns={columns}
            data={tableData}
            options={{search: true }}
        />
    )
}

此更改解决了我的问题,但我真的很想了解为什么会这样。 当我在方法之外定义列时,为什么 memory 泄漏和渲染会减慢每次页面更改的速度。 同时,当我进入 method 时发生了什么变化?

分析

material-tablecolumns列表的每一列添加一个属性column.tableData ,然后有一个有效地执行类似操作的赋值(参见文件data-manager.js ):

column[0].tableData.width = "calc(" + ... +
  column[0].tableData.width + ... +
  column[1].tableData.width + ... + ")"

column[1].tableData.width = "calc(" + ... 
...

因为列在全局范围内并且不会在每次卸载时销毁,这让字符串tableData.width呈指数增长 我猜越来越长的时间来自这些越来越多的嵌套“calc()”调用。

结论

我犹豫是否将其称为材料表中的错误。

看起来 material-table 期望在每次渲染时创建列(而不是持久的)。 很公平,但我至少会为习惯于在React 中工作的人称这种意外行为,并且文档中应该有关于这一点的警告。 我也认为即使那样也可以万无一失地实施。 (如果有人不同意,我想在评论中阅读原因)

例子

组件第一次挂载时tableData.width为:

calc((100% - (0px +
  calc((100% - (0px)) / 3) +
  calc((100% - (0px)) / 3) +
  calc((100% - (0px)) / 3)
)) / 3)

卸载和第二次安装后,宽度tableData.width是:

calc((100% - (0px +
  calc((100% - (0px + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3)
  )) / 3) +
  calc((100% - (0px + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3)
  )) / 3) +
  calc((100% - (0px + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3) + 
    calc((100% - (0px + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3) + calc((100% - (0px)) / 3))) / 3)
  )) / 3)
)) / 3)"

列数组对于材料表实例应该是静态的。 当它被一次又一次地动态调用时,内存填满并最终耗尽空间。

如果您尝试使用 useState 来管理列,则会发生此问题。 我有一个解决方法,每次我都会设置列,但会重置我的分组等。

有一个材料表的分支解决了这个问题: https://material-table-core.com/docs/#installation

npx create-react-app material-table-app
npm uninstall react react-dom
npm install react@17.0.2 react-dom@17.0.2 
npm install @material-table/core@4.3.43 --legacy-deps 

这是对我有用的组合。 使用此设置,我可以使用 useState 来设置我的列/维护它们的 state。

我遇到了无法解决的材料表 ^5.0 的 _deepmerge 问题。 几乎完全放弃了这个 package。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM