How to Create a Table with Draggable Rows in React

Published Feb 17, 2022  ∙  Updated May 2, 2022

I recently tried out react-sortable-hoc to create a table in React with draggable rows.

The process is quite simple with this package.

Install the package

First, we’ll have to install the package. We’ll also need array-move, so let’s install that as well.

npm i react-sortable-hoc array-move --save

Create the SortableComponent component

Let’s create a SortableComponent functional component that will utilize the SortableContainer and SortableElement components from react-sortable-hoc.

// SortableComponent.jsx
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import { arrayMoveImmutable } from 'array-move';

const SortableItem = SortableElement(({ value, i }) => (
  <tr>
    <td>{i}</td>
    <td>{value}</td>
  </tr>
));
const SortableList = SortableContainer(({ items }) => {
  return (
    <tbody>
      {items.map((value, index) => (
        <SortableItem 
          key={`item-${index}`} 
          index={index}
          value={value}
          i={index}
        />
      ))}
    </tbody>
  );
});
export const SortableComponent = ({ items, setItems }) => {
  const onSortEnd = ({ oldIndex, newIndex }) => {
    setItems(prev => arrayMoveImmutable(prev, oldIndex, newIndex));
  };
  return (
    <SortableList
      items={items}
      onSortEnd={onSortEnd}
    />
  )
}

Let’s first look at SortableItem. Each sortable item with be a table row <tr>, each of which contain the appropriate table data cells <td>.

In SortableList, we see that we’re mapping through our state array and creating a <tr> per element. We’re wrapping the entire list of <tr> in a <tbody> tag.

Then, we render SortableList and use the onSortEnd() callback to update our state. Here, we use arrayMoveImmutable() to update the indexes of the array.

Use SortableComponent to create draggable rows

Finally, we can import this component and place it in our table.

import { SortableComponent } from "./SortableComponent";
export const DraggableTableRows = () => {
  const [users, setUsers] = useState<string[]>(["John", "Bob", "Alice"]);
  return (
    <table>
      <thead>
        <tr>
          <th>#</th>
          <th>User</th>
        </tr>
      </thead>
      <SortableComponent items={users} setItems={setUsers} />
    </table>
  )
}

A simple way to view arrays and rearrange the elements.