列排序指南

示例

想要直接跳到实现部分吗?请查看以下示例:

API

列排序 API

列排序指南

默认情况下,列按照它们在 columns 数组中定义的顺序进行排序。但是,您可以使用 columnOrder 状态手动指定列顺序。其他功能(如列固定和分组)也会影响列顺序。

影响列顺序的因素

有 3 个表格功能可以重新排序列,它们按以下顺序发生:

  1. 列固定 - 如果固定,列将分为左侧、中间(未固定)和右侧固定列。
  2. 手动列排序 - 应用手动指定的列顺序。
  3. 分组 - 如果启用了分组,分组状态处于活动状态,��且 tableOptions.groupedColumnMode 设置为 'reorder' | 'remove',则分组的列将重新排序到列流的开头。

注意: 如果与列固定结合使用,columnOrder 状态将仅影响未固定的列。

列顺序状态

如果您不提供 columnOrder 状态,TanStack Table 将只使用 columns 数组中列的顺序。但是,您可以向 columnOrder 状态提供一个字符串列 ID 数组来指定列的顺序。

默认列顺序

如果您只需要指定初始列顺序,则只需在 initialState 表格选项中指定 columnOrder 状态即可。

jsx
const table = useReactTable({
  //...
  initialState: {
    columnOrder: ['columnId1', 'columnId2', 'columnId3'],
  }
  //...
});
const table = useReactTable({
  //...
  initialState: {
    columnOrder: ['columnId1', 'columnId2', 'columnId3'],
  }
  //...
});

注意: 如果您正在使用 state 表格选项来同时指定 columnOrder 状态,则 initialState 将不起作用。仅在 initialStatestate 中指定特定状态,而不是两者都指定。

管理列顺序状态

如果您需要动态更改列顺序,或在表格初始化后设置列顺序,则可以像管理任何其他表格状态一样管理 columnOrder 状态。

jsx
const [columnOrder, setColumnOrder] = useState<string[]>(['columnId1', 'columnId2', 'columnId3']); //可选择初始化列顺序
//...
const table = useReactTable({
  //...
  state: {
    columnOrder,
    //...
  }
  onColumnOrderChange: setColumnOrder,
  //...
});
const [columnOrder, setColumnOrder] = useState<string[]>(['columnId1', 'columnId2', 'columnId3']); //可选择初始化列顺序
//...
const table = useReactTable({
  //...
  state: {
    columnOrder,
    //...
  }
  onColumnOrderChange: setColumnOrder,
  //...
});

重新排序列

如果表格具有允许用户重新排序列的 UI,您可以像这样设置逻辑:

tsx
const [columnOrder, setColumnOrder] = useState<string[]>(columns.map(c => c.id));

//根据您选择的 dnd 解决方案,您可能需要也可能不需要这样的状态
const [movingColumnId, setMovingColumnId] = useState<string | null>(null);
const [targetColumnId, setTargetColumnId] = useState<string | null>(null);

//用于拼接和重新排序 columnOrder 数组的实用函数
const reorderColumn = <TData extends RowData>(
  movingColumnId: Column<TData>,
  targetColumnId: Column<TData>,
): string[] => {
  const newColumnOrder = [...columnOrder];
  newColumnOrder.splice(
    newColumnOrder.indexOf(targetColumnId),
    0,
    newColumnOrder.splice(newColumnOrder.indexOf(movingColumnId), 1)[0],
  );
  setColumnOrder(newColumnOrder);
};

const handleDragEnd = (e: DragEvent) => {
  if(!movingColumnId || !targetColumnId) return;
  setColumnOrder(reorderColumn(movingColumnId, targetColumnId));
};

//使用您选择的 dnd 解决方案
const [columnOrder, setColumnOrder] = useState<string[]>(columns.map(c => c.id));

//根据您选择的 dnd 解决方案,您可能需要也可能不需要这样的状态
const [movingColumnId, setMovingColumnId] = useState<string | null>(null);
const [targetColumnId, setTargetColumnId] = useState<string | null>(null);

//用于拼接和重新排序 columnOrder 数组的实用函数
const reorderColumn = <TData extends RowData>(
  movingColumnId: Column<TData>,
  targetColumnId: Column<TData>,
): string[] => {
  const newColumnOrder = [...columnOrder];
  newColumnOrder.splice(
    newColumnOrder.indexOf(targetColumnId),
    0,
    newColumnOrder.splice(newColumnOrder.indexOf(movingColumnId), 1)[0],
  );
  setColumnOrder(newColumnOrder);
};

const handleDragEnd = (e: DragEvent) => {
  if(!movingColumnId || !targetColumnId) return;
  setColumnOrder(reorderColumn(movingColumnId, targetColumnId));
};

//使用您选择的 dnd 解决方案

拖放列重新排序建议 (React)

毫无疑问,有很多方法可以与 TanStack Table 一起实现拖放功能。以下是一些建议,以免您遇到麻烦:

  1. 如果您使用的是 React 18 或更高版本,请不要尝试使用 "react-dnd"。React DnD 在当时是一个重要的库,但现在更新频率不高,并且与 React 18 不兼容,尤其是在 React 严格模式下。仍然可以让它工作,但有更新的替代方案具有更好的兼容性并且维护更积极。React DnD 的 Provider 也可能会干扰和冲突您可能想在应用程序中尝试的任何其他 DnD 解决方案。

  2. 使用 "@dnd-kit/core"。DnD Kit 是一个现代、模块化和轻量级的拖放库,与现代 React 生态系统高度兼容,并且与语义 <table> 标记配合良好。两个官方的 TanStack DnD 示例,列 DnD行 DnD,现在都使用 DnD Kit。

  3. 考虑其他 DnD 库,例如 "react-beautiful-dnd",但要注意它们潜在的较大包大小、维护状态以及与 <table> 标记的兼容性。

  4. 考虑使用本机浏览器事件和状态管理来实现轻量级的拖放功能。但是,请注意,如果您不额外努力实现适当的触摸事件,则此方法可能不适合移动用户。Material React Table V2 是一个库的示例,它仅使用浏览器拖放事件(例如 onDragStartonDragEndonDragEnter)实现 TanStack Table,并且没有其他依赖项。浏览其源代码以了解其实现方式。