MUI Datagrid - TypeError: Cannot read properties of undefined (reading 'name')
MUI Datagrid - TypeError: Cannot read properties of undefined (reading 'name')
我正在使用 Material UI 的数据网格在 table 中显示一些数据,我最近从 redux 切换到 RTK 查询以进行缓存并摆脱全局项目中的状态管理却遇到了标题中提到的问题
我目前看到的错误是 TypeError: Cannot read properties of undefined (reading 'name')
尝试获取嵌套 object 中的数据时会发生这种情况,我正在使用 valueGetter
获取嵌套值。下面的 const 显示了 table 的列以及使用 valueGetter
的位置(我已经删除了这个例子中的一些列)
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{
field: "App",
headerName: "App",
width: 110,
valueGetter: (params) => params.row.app.name, // <---- Recieving error here
valueFormatter: (params) => capitalise(params.value),
}
];
这是我的组件的样子(我还删除了一些代码只是为了这个例子):
import React, { useEffect, useState } from "react";
import { DataGrid } from "@mui/x-data-grid";
import { IconButton } from "@material-ui/core";
import { CustomLoadingOverlay } from "../gbl/datagrid/DataGridUtils";
import { capitalise } from "../utils/util";
import {
useGetAppAccountTypesQuery,
useDeleteAccountTypeMutation,
} from "../../services/reducers/accounttypes";
export default ({ appid }) => {
const { data, isLoading, isSuccess } = useGetAppAccountTypesQuery(appid);
const [loading, setLoading] = useState(true);
console.log(data, isLoading, isSuccess);
// Testing only
useEffect(() => {
if (isSuccess) setLoading(false);
}, [isLoading]);
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{
field: "App",
headerName: "App",
width: 110,
valueGetter: (params) => params.row.app.name,
valueFormatter: (params) => capitalise(params.value),
}
];
return (
<>
<div
style={{
height: 190,
width: "100%",
backgroundColor: "white",
marginTop: 40,
borderRadius: 4,
}}
>
<DataGrid
loading={loading}
rows={data}
columns={columns}
components={{
LoadingOverlay: CustomLoadingOverlay,
}}
hideFooter
density="compact"
pageSize={6}
rowsPerPageOptions={[5]}
checkboxSelection
disableSelectionOnClick
></DataGrid>
</div>
</>
);
};
组件re-renders几次,每次渲染console.log(data, isLoading, isSuccess)
看起来像
undefined true false <---- this gets logged 3 times
Array(2) false true
Array(2) false true
这个问题似乎是间歇性的,因为它有时会起作用,
在切换到 RTK 查询之前,我正在使用 Axios 和 useEffect 调用端点并且从未收到此错误,我在这里做错了吗?
如有任何帮助,我们将不胜感激。
我想说这里和RTK-Q本身没有任何关系,它只是一个普通的JS problem\question,应该缩小到null-check。
在某些情况下,您可能会得到未定义的结果,这很正常,应该在代码中对其进行处理。可能有几种选择:
最正确的方法是 return 空对象或加载状态,如 spinner\skeleton,当数据未定义时 and\or data isLoading = true :
const { data, isLoading, isSuccess } = useGetAppAccountTypesQuery(appid);
if (!data || isLoading) return <>骨架或微调器>;
通常 - 使用 null-safe ?
访问器:
valueGetter: (params) => params?.row?.app?.name,
使用一些对象结构设置 data
的默认值,该对象结构应与正确列配置的默认状态相匹配:
常数DEFAULT_DATA = {
排: {
应用程序: {
姓名: ””
}
}
}
const { data = DEFAULT_DATA, isLoading, isSuccess } = useGetAppAccountTypesQuery(appid);
当数据未定义时,在数据加载期间什么都不做:
常量列 = 数据? [...您的列映射...] : [];
您可以结合使用它们,在加载时间内达到预期的结果。
注意选型。即:第一次单击一行或单元格时,选择模型是一个包含一项的数组:所选行的索引。如果您再次单击同一行,则选择模型为空(该行未被选中)
selectionModel={selectionModel}
onSelectionModelChange={(selection) => {
const selectionSet = new Set(selectionModel);
const result = selection.filter((s) => !selectionSet.has(s))
setSelectionModel(result)
if(result.length > 0)
// save de selection model on click on a row
setRecursoSelected(rows[result[0]])
else
// after clicking the same row (unselected)
setRecursoSelected({})
}}
我正在使用 Material UI 的数据网格在 table 中显示一些数据,我最近从 redux 切换到 RTK 查询以进行缓存并摆脱全局项目中的状态管理却遇到了标题中提到的问题
我目前看到的错误是 TypeError: Cannot read properties of undefined (reading 'name')
尝试获取嵌套 object 中的数据时会发生这种情况,我正在使用 valueGetter
获取嵌套值。下面的 const 显示了 table 的列以及使用 valueGetter
的位置(我已经删除了这个例子中的一些列)
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{
field: "App",
headerName: "App",
width: 110,
valueGetter: (params) => params.row.app.name, // <---- Recieving error here
valueFormatter: (params) => capitalise(params.value),
}
];
这是我的组件的样子(我还删除了一些代码只是为了这个例子):
import React, { useEffect, useState } from "react";
import { DataGrid } from "@mui/x-data-grid";
import { IconButton } from "@material-ui/core";
import { CustomLoadingOverlay } from "../gbl/datagrid/DataGridUtils";
import { capitalise } from "../utils/util";
import {
useGetAppAccountTypesQuery,
useDeleteAccountTypeMutation,
} from "../../services/reducers/accounttypes";
export default ({ appid }) => {
const { data, isLoading, isSuccess } = useGetAppAccountTypesQuery(appid);
const [loading, setLoading] = useState(true);
console.log(data, isLoading, isSuccess);
// Testing only
useEffect(() => {
if (isSuccess) setLoading(false);
}, [isLoading]);
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{
field: "App",
headerName: "App",
width: 110,
valueGetter: (params) => params.row.app.name,
valueFormatter: (params) => capitalise(params.value),
}
];
return (
<>
<div
style={{
height: 190,
width: "100%",
backgroundColor: "white",
marginTop: 40,
borderRadius: 4,
}}
>
<DataGrid
loading={loading}
rows={data}
columns={columns}
components={{
LoadingOverlay: CustomLoadingOverlay,
}}
hideFooter
density="compact"
pageSize={6}
rowsPerPageOptions={[5]}
checkboxSelection
disableSelectionOnClick
></DataGrid>
</div>
</>
);
};
组件re-renders几次,每次渲染console.log(data, isLoading, isSuccess)
看起来像
undefined true false <---- this gets logged 3 times
Array(2) false true
Array(2) false true
这个问题似乎是间歇性的,因为它有时会起作用,
在切换到 RTK 查询之前,我正在使用 Axios 和 useEffect 调用端点并且从未收到此错误,我在这里做错了吗?
如有任何帮助,我们将不胜感激。
我想说这里和RTK-Q本身没有任何关系,它只是一个普通的JS problem\question,应该缩小到null-check。 在某些情况下,您可能会得到未定义的结果,这很正常,应该在代码中对其进行处理。可能有几种选择:
最正确的方法是 return 空对象或加载状态,如 spinner\skeleton,当数据未定义时 and\or data isLoading = true :
const { data, isLoading, isSuccess } = useGetAppAccountTypesQuery(appid);
if (!data || isLoading) return <>骨架或微调器>;
通常 - 使用 null-safe
?
访问器:valueGetter: (params) => params?.row?.app?.name,
使用一些对象结构设置
data
的默认值,该对象结构应与正确列配置的默认状态相匹配:常数DEFAULT_DATA = { 排: { 应用程序: { 姓名: ”” } } }
const { data = DEFAULT_DATA, isLoading, isSuccess } = useGetAppAccountTypesQuery(appid);
当数据未定义时,在数据加载期间什么都不做:
常量列 = 数据? [...您的列映射...] : [];
您可以结合使用它们,在加载时间内达到预期的结果。
注意选型。即:第一次单击一行或单元格时,选择模型是一个包含一项的数组:所选行的索引。如果您再次单击同一行,则选择模型为空(该行未被选中)
selectionModel={selectionModel}
onSelectionModelChange={(selection) => {
const selectionSet = new Set(selectionModel);
const result = selection.filter((s) => !selectionSet.has(s))
setSelectionModel(result)
if(result.length > 0)
// save de selection model on click on a row
setRecursoSelected(rows[result[0]])
else
// after clicking the same row (unselected)
setRecursoSelected({})
}}