You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@tanstack/react-table删除表格行的状态异常问题求助

解决TanStack React Table外部按钮删除行并同步选中状态的问题

核心问题分析

  • TanStack Table默认可能用行索引或内部生成ID作为row.id,和业务数据的原始ID不一致,导致删除时选中状态和数据行不匹配
  • 父组件和子组件的选中状态没有完全同步,删除后未及时清空选中状态,引发表头复选框异常、错误选中下一行的问题

解决方案步骤

1. 统一行ID为业务原始ID

在表格配置中通过getRowId指定用数据的原始ID作为行的唯一标识,确保表格内部的行ID和业务ID完全一致:

const table = useReactTable({
  columns,
  data,
  getRowId: row => row.id, // 替换成你数据中的原始ID字段名
  // 其他配置项
})

2. 让父组件完全控制选中状态

  • 父组件维护selectedRowIds状态(存储选中的原始ID数组),并传递给子组件
  • 子组件通过state.selectedRowIds和onSelectedRowIdsChange绑定父组件的状态,实现双向同步:

父组件代码片段

const [data, setData] = useState(initialData);
const [selectedRowIds, setSelectedRowIds] = useState([]);

const handleDelete = () => {
  // 过滤掉选中的行
  const updatedData = data.filter(item => !selectedRowIds.includes(item.id));
  setData(updatedData);
  // 清空选中状态
  setSelectedRowIds([]);
};

子组件AppTable配置

const table = useReactTable({
  columns,
  data,
  getRowId: row => row.id,
  state: {
    selectedRowIds: props.selectedRowIds, // 绑定父组件传入的选中状态
  },
  onSelectedRowIdsChange: updater => {
    // 将表格内部的选中变更同步到父组件
    props.setSelectedRowIds(updater(props.selectedRowIds));
  },
  getCoreRowModel: getCoreRowModel(),
  getSelectedRowModel: getSelectedRowModel(),
})

3. 验证效果

  • 删除选中行后,selectedRowIds被清空,表格的选中状态会自动同步更新,表头复选框会恢复未选中状态
  • 因为用原始ID作为行标识,删除行后不会出现下一行被错误选中的问题

完整代码示例

父组件

import { useState } from 'react';
import AppTable from './AppTable';

const initialData = [
  { id: 1, name: '第一行' },
  { id: 2, name: '第二行' },
  { id: 3, name: '第三行' },
];

export default function ParentComponent() {
  const [data, setData] = useState(initialData);
  const [selectedRowIds, setSelectedRowIds] = useState([]);

  const handleDelete = () => {
    setData(prevData => prevData.filter(item => !selectedRowIds.includes(item.id)));
    setSelectedRowIds([]);
  };

  return (
    <div style={{ padding: '20px' }}>
      <button onClick={handleDelete} style={{ marginBottom: '10px' }}>
        删除选中行
      </button>
      <AppTable 
        data={data} 
        selectedRowIds={selectedRowIds} 
        setSelectedRowIds={setSelectedRowIds} 
      />
    </div>
  );
}

子组件AppTable

import { useReactTable, getCoreRowModel, getSelectedRowModel, flexRender } from '@tanstack/react-table';

export default function AppTable({ data, selectedRowIds, setSelectedRowIds }) {
  const columns = [
    {
      id: 'select',
      header: ({ table }) => (
        <input
          type="checkbox"
          checked={table.getIsAllRowsSelected()}
          onChange={table.getToggleAllRowsSelectedHandler()}
        />
      ),
      cell: ({ row }) => (
        <input
          type="checkbox"
          checked={row.getIsSelected()}
          onChange={row.getToggleSelectedHandler()}
        />
      ),
    },
    {
      accessorKey: 'name',
      header: '行名称',
    },
  ];

  const table = useReactTable({
    columns,
    data,
    getRowId: row => row.id,
    state: {
      selectedRowIds,
    },
    onSelectedRowIdsChange: updater => {
      setSelectedRowIds(updater(selectedRowIds));
    },
    getCoreRowModel: getCoreRowModel(),
    getSelectedRowModel: getSelectedRowModel(),
  });

  return (
    <table border="1" cellPadding="8">
      <thead>
        {table.getHeaderGroups().map(headerGroup => (
          <tr key={headerGroup.id}>
            {headerGroup.headers.map(header => (
              <th key={header.id}>
                {flexRender(header.column.columnDef.header, header.getContext())}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody>
        {table.getRowModel().rows.map(row => (
          <tr key={row.id}>
            {row.getVisibleCells().map(cell => (
              <td key={cell.id}>
                {flexRender(cell.column.columnDef.cell, cell.getContext())}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
}

内容的提问来源于stack exchange,提问作者Yuri Dukhanin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 21:37:53