typescript 如何处理TanStack表中的一对多关系(React-Table V8)

1zmg4dgp  于 2023-01-03  发布在  TypeScript
关注(0)|答案(1)|浏览(117)
    • bounty将在6天后过期**。回答此问题可获得+50声望奖励。Alexander Stolz希望引起更多人关注此问题。

我目前正在尝试Tanstack Table,这是一个很棒的库!
我要做的是建立一个类似这样的表:

我的数据来自以下类型的API:

type Accounting = {
  category: string;
  total: number; // Sum of all expenses
  expenses: {
    name: string;
    value: number;
  }[];
};

以下是我目前所了解到的:

const columns = React.useMemo(
    () => [
      columnHelper.accessor("category", {
        header: "Category",
        id: "category",
        cell: (info) => {
          return (
            <>
              {info.row.getCanExpand() && (
                <button
                  {...{
                    onClick: info.row.getToggleExpandedHandler(),
                    style: { cursor: "pointer" },
                    className: "mr-2",
                  }}
                >
                  {info.row.getIsExpanded() ? (
                    <Chevron direction="down" />
                  ) : (
                    <Chevron direction="right" />
                  )}
                </button>
              )}
              {info.getValue()}
            </>
          );
        },
      }),
      columnHelper.accessor("expenses", {
        header: undefined,
        id: "expense-name",
        cell: (info) => {
          // FIXME : this returns a table of objects, I want one row per expense
          return info.getValue();
        },
      }),
      columnHelper.accessor("expenses", {
        aggregationFn: "sum",
        id: "expense-value",
        header: "Expense",
        cell: (info) => {
          // FIXME : this returns a table of objects, I want one row per expense
          return info.getValue();
        },
      }),
    ],
    []
  );

  const grouping = React.useMemo(() => ["category"], []);

  const table = useReactTable({
    data,
    columns,
    state: {
      grouping,
      expanded,
    },
    getExpandedRowModel: getExpandedRowModel(),
    getGroupedRowModel: getGroupedRowModel(),
    getCoreRowModel: getCoreRowModel(),
    onExpandedChange: setExpanded,
    autoResetExpanded: false,
  });

这里的问题是,我在一个类别和该类别的多个费用之间建立了一对多的关系。
上面的代码不起作用,因为tanstack表试图呈现一个对象列表(一个费用列表)。
我还没有弄清楚Tansack Table是如何处理这个的?我应该重写一些渲染方法吗?Tansack Table是处理这类数据的好选择吗?
尊敬的。

0md85ypi

0md85ypi1#

您可以从React Table Expanding Example中获得很多信息。
缺少的关键部分是表中的getSubRows函数,我们不想在父类别的cell中呈现单个费用,而是想在表中为每个费用创建一个新行。
我们的两列是标题和数字。对于顶层Accounting对象,它是categorytotal。对于单个费用,它是namevalue。由于它们是不同的属性,我们需要做一些Map。
让我们从非常简单的开始,为顶层对象定义这两列:

const columns = React.useMemo(
  () => [
    columnHelper.accessor("category", {
      header: "Category",
      id: "category"
    }),
    columnHelper.accessor("total", {
      header: "Expense",
      id: "expense-value"
    })
  ],
  []
);

现在,让我们添加扩展功能(您不需要分组功能)。
我们将把expanded状态存储在组件中,并将其传递给表,通过onExpandedChange选项同步更改。
我们将在表中添加一个新的getSubRows选项。这个函数接受父对象Accounting,并返回一个子对象Accounting的数组。如前所述,我们需要重命名一些属性来匹配接口。我们的columns配置需要一个带有categorytotal的对象。我在这里设置了一个空数组expenses,因为子行没有自己的子行。

const [expanded, setExpanded] = React.useState<ExpandedState>({});

const table = useReactTable({
  data,
  columns,
  state: {
    expanded
  },
  getExpandedRowModel: getExpandedRowModel(),
  getCoreRowModel: getCoreRowModel(),
  onExpandedChange: setExpanded,
  getSubRows: (originalRow) =>
    originalRow.expenses.map((expense) => ({
      category: expense.name,
      total: expense.value,
      expenses: []
    }))
});

对于您的列,我对前面的列所做的唯一更改是在父行上显示一个展开/收缩按钮(您已经尝试过了)。

const columns = React.useMemo(
  () => [
    columnHelper.accessor("category", {
      header: "Category",
      id: "category",
      cell: (info) => {
        return (
          <>
            {info.row.getCanExpand() && (
              <button onClick={info.row.getToggleExpandedHandler()}>
                {info.row.getIsExpanded() ? "-" : "+"}
              </button>
            )}
            {info.getValue()}
          </>
        );
      }
    }),
    columnHelper.accessor("total", {
      header: "Expense",
      id: "expense-value"
    })
  ],
  []
);

现在我们有了全功能的行扩展。它并不漂亮,但我会让您添加样式。
CodeSandbox Demo

相关问题