Drag and drop interface on a touchscreen with React Movable code visible on nearby monitors

React Movable: Mastering Drag and Drop for Lists and Tables

The Orange Cat
The Orange Cat

React Movable is a lightweight and powerful library that brings smooth, animated drag and drop functionality to your React applications. With a focus on accessibility and performance, it’s an excellent choice for developers looking to implement interactive lists and tables. In this article, we’ll explore the features of React Movable and learn how to use it effectively in your projects.

Features

React Movable offers a range of features that make it stand out from other drag and drop libraries:

  • Vertical drag and drop: Seamlessly rearrange items in lists and tables.
  • Minimal markup: No additional wrapping divs or markup required.
  • Simplicity: Single component with no providers or higher-order components.
  • Flexible styling: Works great with CSS-in-JS solutions.
  • Accessibility: Full support for keyboards and screen readers.
  • Touch support: Works on mobile devices.
  • Full control: Dragged item is a portaled React component.
  • Autoscrolling: Supports both container and window scrolling.
  • Smooth animations: Can be disabled if needed.
  • Variable heights: Supports items with different heights.
  • Axis locking: Optional horizontal axis lock when dragging.
  • Lightweight: No dependencies and less than 4kB gzipped.

Installation

To get started with React Movable, install it using npm or yarn:

npm install react-movable

or

yarn add react-movable

Basic Usage

Let’s dive into a simple example to demonstrate how easy it is to use React Movable:

import * as React from "react";
import { List, arrayMove } from "react-movable";

const SimpleList: React.FC = () => {
  const [items, setItems] = React.useState(["Item 1", "Item 2", "Item 3"]);

  return (
    <List
      values={items}
      onChange={({ oldIndex, newIndex }) =>
        setItems(arrayMove(items, oldIndex, newIndex))
      }
      renderList={({ children, props }) => <ul {...props}>{children}</ul>}
      renderItem={({ value, props }) => <li {...props}>{value}</li>}
    />
  );
};

In this example, we create a simple list with three items. The List component from React Movable handles the drag and drop functionality, while we provide the rendering logic for the list and its items.

Understanding the Props

Let’s break down the key props used in the List component:

  • values: An array of items to be rendered in the list.
  • onChange: A callback function that’s called when an item is moved. It receives the old and new indices of the moved item.
  • renderList: A function that defines how to render the container of the list.
  • renderItem: A function that defines how to render each item in the list.

Advanced Usage

Custom Components

React Movable allows you to use custom components for rendering list items. Here’s an example:

import * as React from "react";
import { List, arrayMove } from "react-movable";

const CustomItem = React.forwardRef(({ value, ...props }, ref) => (
  <div ref={ref} {...props} style={{ padding: "10px", background: "#f0f0f0", marginBottom: "5px" }}>
    {value}
  </div>
));

const AdvancedList: React.FC = () => {
  const [items, setItems] = React.useState(["Custom Item 1", "Custom Item 2", "Custom Item 3"]);

  return (
    <List
      values={items}
      onChange={({ oldIndex, newIndex }) =>
        setItems(arrayMove(items, oldIndex, newIndex))
      }
      renderList={({ children, props }) => <div {...props}>{children}</div>}
      renderItem={({ value, props }) => <CustomItem value={value} {...props} />}
    />
  );
};

In this example, we’ve created a custom CustomItem component to render each item in the list. Note the use of React.forwardRef to properly handle the ref passed by React Movable.

Removable Items

React Movable supports removing items by dragging them out of bounds. Here’s how to implement this feature:

import * as React from "react";
import { List, arrayMove, arrayRemove } from "react-movable";

const RemovableList: React.FC = () => {
  const [items, setItems] = React.useState(["Item 1", "Item 2", "Item 3"]);

  return (
    <List
      values={items}
      onChange={({ oldIndex, newIndex }) => {
        if (newIndex === -1) {
          setItems(arrayRemove(items, oldIndex));
        } else {
          setItems(arrayMove(items, oldIndex, newIndex));
        }
      }}
      renderList={({ children, props }) => <ul {...props}>{children}</ul>}
      renderItem={({ value, props }) => <li {...props}>{value}</li>}
      removableByMove
    />
  );
};

The removableByMove prop enables this feature, and we handle the removal in the onChange callback when newIndex is -1.

Accessibility Features

React Movable is designed with accessibility in mind. It supports keyboard navigation and works well with screen readers. Here are the key keyboard controls:

  • Tab and Shift+Tab: Focus items
  • Space: Lift or drop the item
  • J or Arrow Down: Move the lifted item down
  • K or Arrow Up: Move the lifted item up
  • Escape: Cancel the lift and return the item to its initial position

Customizing Animations

React Movable provides smooth animations by default. You can customize the animation duration or disable animations entirely:

<List
  // ... other props
  transitionDuration={500} // Set custom duration in milliseconds
  // or
  transitionDuration={0} // Disable animations
/>

Conclusion

React Movable offers a powerful yet simple solution for implementing drag and drop functionality in React applications. Its focus on accessibility, performance, and ease of use makes it an excellent choice for developers looking to create interactive lists and tables.

By leveraging React Movable’s features, you can create engaging user interfaces that allow for intuitive item reordering without sacrificing performance or accessibility. Whether you’re building a simple todo list or a complex data table, React Movable provides the tools you need to implement smooth, animated drag and drop functionality in your React projects.

Comments