为什么当我关闭并重新打开 React 组件 (material-table) 时会发生内存泄漏并导致渲染速度变慢?
Why memory leak happend and render slowing down when I close and re-open react component (material-table)?
我有用于学习的基本反应示例,并且在我的组件之一中使用了 material-table。每次我更改页面并重新打开它(卸载和安装组件)时,我的包含 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 }}
/>
)
}
此更改解决了我的问题,但我真的很想了解发生这种情况的原因。当我在方法之外定义列时,为什么内存泄漏和渲染会减慢每次页面更改的速度。同时,当我进入方法时发生了什么变化?
分析
material-table adds a property column.tableData
to each column of your columns
list, and then there is an assignment that effectively does something like (see file 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 中的错误。
看起来 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)"
列数组对于 material table 实例应该是静态的。当一次又一次动态调用时,内存被填满,最后用完space.
我有用于学习的基本反应示例,并且在我的组件之一中使用了 material-table。每次我更改页面并重新打开它(卸载和安装组件)时,我的包含 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 }}
/>
)
}
此更改解决了我的问题,但我真的很想了解发生这种情况的原因。当我在方法之外定义列时,为什么内存泄漏和渲染会减慢每次页面更改的速度。同时,当我进入方法时发生了什么变化?
分析
material-table adds a property column.tableData
to each column of your columns
list, and then there is an assignment that effectively does something like (see file 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 中的错误。
看起来 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)"
列数组对于 material table 实例应该是静态的。当一次又一次动态调用时,内存被填满,最后用完space.