MUI 数据网格 - 类型错误:无法读取未定义的属性(读取"名称")



我使用Material UI的数据网格在表中显示一些数据,我最近从redux切换到RTK查询进行缓存,并在项目中摆脱全局状态管理,但遇到了标题中提到的问题。

我目前看到的错误是TypeError: Cannot read properties of undefined (reading 'name')

当尝试在嵌套对象中获取数据时,会发生这种情况,我使用valueGetter来获取嵌套值。下面的const显示了表的列和使用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>
    </>
  );
};

组件重新渲染几次,从每次渲染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问题,应该缩小到空检查。在某些情况下,您可能会有一个未定义的结果,这是正常的,应该在代码中处理它。可能有几个选项:

  1. 最正确的方法是返回一个空对象或加载状态,如spinnerskeleton,当数据未定义和或data isLoading = true:

    const {data, isLoading, isSuccess} = useGetAppAccountTypesQuery(appid);

    如果( !data || isLoading) return <>Skeleton or Spinner;

  2. 一般-使用null安全的?访问器:

    valueGetter: (params) =>params .row ? .app ? . name,

  3. data设置一些对象结构的默认值,这些对象结构应该与您的默认状态相匹配。

    const DEFAULT_DATA = {行:{应用:{名称:"}}}

    const {data = DEFAULT_DATA, isLoading, isSuccess} = useGetAppAccountTypesQuery(appid);

  4. 当数据未定义时,在数据加载期间什么都不做:

    const columns = data ?[…你的列映射…[c]: [c];

您可以组合使用它们,在加载期间达到预期的结果。

注意选择模型。即:第一次单击行或单元格时,选择模型是一个包含一个项目的数组:所选行的索引。如果再次单击同一行,则选择模型为空(该行未被选中)

  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({})
  }}

最新更新