Blog>
Snippets

Integrating Drag-and-Drop for Column Reordering

Exemplify the integration of a third-party drag-and-drop library with TanStack Table for intuitive column reordering capabilities.
import { useReactTable, createColumnHelper } from '@tanstack/react-table';
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, } from '@dnd-kit/core';
import { arrayMove, SortableContext, verticalListSortingStrategy, } from '@dnd-kit/sortable';
import { useSortable, sortableKeyboardCoordinates, } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
This code imports necessary hooks and components from TanStack Table and DND Kit to enable drag-and-drop functionality for column reordering.
const columns = React.useMemo(() => [
    // Define columns
], []);
Here we define the table columns, typically as a useMemo hook to ensure they are not recalculated on every render.
const DraggableColumn = ({ id, children }) => {
    const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
    };

    return (
        <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
            {children}
        </div>
    );
};
Defines a DraggableColumn component that makes each column header draggable, utilizing the DND Kit's sortable utilities for managing drag-and-drop state and styles.
const ReorderableTableHeader = ({ columns }) => {
    const sensors = useSensors(
        useSensor(PointerSensor),
        useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
    );

    const handleDragEnd = (event) => {
        const { active, over } = event;
        if (active.id !== over.id) {
            setColumns((prevColumns) => {
                const oldIndex = prevColumns.findIndex((column) => column.accessor === active.id);
                const newIndex = prevColumns.findIndex((column) => column.accessor === over.id);
                return arrayMove(prevColumns, oldIndex, newIndex);
            });
        }
    };

    return (
        <DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
            <SortableContext items={columns.map(column => column.accessor)} strategy={verticalListSortingStrategy}>
                {columns.map((column) => (
                    <DraggableColumn key={column.accessor} id={column.accessor}>{column.Header}</DraggableColumn>
                ))}
            </SortableContext>
        </DndContext>
    );
};
Creates a ReorderableTableHeader component which wraps the table headers in a draggable context allowing for the reordering of columns. Includes drag end logic to reorder columns state.