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

TanStack Table(React)拖拽排序与行选择功能整合后失效问题求助

TanStack Table(React)拖拽排序与行选择功能整合后失效问题求助

大家好,我最近在React项目里用TanStack Table开发表格功能,遇到了一个棘手的问题,想请各位帮忙解决:

我原本有一个可以正常实现单行列拖拽重排的TanStack Table,现在想给它加上官方文档里演示的**行选择(复选框)**功能。我参照官方的行选择示例尝试把逻辑整合到自己的拖拽表格里,但整合后出现了异常:只能成功拖拽一次行,之后拖拽功能就完全失效了。

我希望能有人帮忙把行选择复选框功能正确添加到我的拖拽表格中,同时解决拖拽一次就失效的问题。以下是我的代码:

App.js

import "./styles.css";
import Table from "./Table.js"; // 按需调整路径
import { arrayMove } from "@dnd-kit/sortable";
import { useState } from "react";

export default function App() {
  const [testData, setTestData] = useState([
    { id: "a1", fileName: "Test Audio 1", duration: "2:30" },
    { id: "a2", fileName: "Test Audio 2", duration: "3:45" },
    { id: "a3", fileName: "Test Audio 3", duration: "4:15" },
  ]);

  const testColumns = [
    { accessorKey: "draggable", header: "Drag" },
    { accessorKey: "fileName", header: "File Name" },
    { accessorKey: "duration", header: "Duration" },
  ];

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Table
        data={testData}
        setData={(oldData, active, over) => {
          const oldIndex = oldData.findIndex((row) => row.id === active.id);
          const newIndex = oldData.findIndex((row) => row.id === over.id);

          if (oldIndex !== -1 && newIndex !== -1) {
            const newData = arrayMove(oldData, oldIndex, newIndex);
            setTestData(newData);
          }
        }}
        columns={testColumns}
      />
    </div>
  );
}

Table.js

import React from "react";
import {
  ColumnDef,
  getCoreRowModel,
  useReactTable,
  flexRender,
} from "@tanstack/react-table";
import { DndContext, closestCenter } from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import styles from "./Table.module.css";

// 行拖拽手柄组件
function DragHandle({ row }) {
  const { attributes, listeners } = useSortable({ id: row.original.id });

  return (
    <button
      {...attributes}
      {...listeners}
      className={styles.dragHandle}
      title="Drag to reorder"
    >
      
    </button>
  );
}

// 表格行组件
function Row({ row }) {
  const { attributes, listeners, setNodeRef, transform, transition } =
    useSortable({
      id: row.original.id,
    });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };

  return (
    <tr
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      className={styles.row}
    >
      {row.getVisibleCells().map((cell, index) => (
        <td key={cell.id} className={styles.cell}>
          {index === 0 ? <DragHandle row={row} /> : null}
          {flexRender(cell.column.columnDef.cell, cell.getContext())}
        </td>
      ))}
    </tr>
  );
}

// 表格主组件
function Table({ data, setData, columns }) {
  const tableColumns = React.useMemo(() => [...columns], [columns]);

  const table = useReactTable({
    data,
    columns: tableColumns,
    getCoreRowModel: getCoreRowModel(),
  });

  const handleDragEnd = (event) => {
    const { active, over } = event;

    if (!active?.id || !over?.id || active.id === over.id) {
      return;
    }

    setData(data, active, over);
  };

  return (
    <DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
      <SortableContext
        items={data.map((row) => row.id)}
        strategy={verticalListSortingStrategy}
      >
        <table className={styles.table}>
          <thead>
            {table.getHeaderGroups().map((headerGroup) => (
              <tr key={headerGroup.id} className={styles.headerRow}>
                {headerGroup.headers.map((header) => (
                  <th key={header.id} className={styles.headerCell}>
                    {flexRender(
                      header.column.columnDef.header,
                      header.getContext()
                    )}
                  </th>
                ))}
              </tr>
            ))}
          </thead>
          <tbody>
            {table.getRowModel().rows.map((row) => (
              <Row key={row.id} row={row} />
            ))}
          </tbody>
        </table>
      </SortableContext>
    </DndContext>
  );
}

export default Table;

备注:内容来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 18:13:01