React Movable: Mastering Drag and Drop for Lists and Tables
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
andShift+Tab
: Focus itemsSpace
: Lift or drop the itemJ
orArrow Down
: Move the lifted item downK
orArrow Up
: Move the lifted item upEscape
: 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.