This component allows me to implement a drag-and-drop interface for reordering items. It’s flexible enough to handle both single-level and nested lists. I’m using the @dnd-kit
library to make dragging smooth and intuitive.
Make sure I have the necessary dependencies installed:
npm install @dnd-kit/core @dnd-kit/modifiers @dnd-kit/sortable @dnd-kit/utilities
I’ll need to import the component and create my items. Each item should have a unique ID, and if it has nested items, I’ll add a data
property with its own array.
import React, { useReducer } from "react";
import DndListComponent from "./DndListComponent";
// Initial items for the list
const initialItems = [
{ id: "1", content: "Item 1" },
{ id: "2", content: "Item 2" },
{ id: "3", content: "Item 3" },
];
// Reducer function to handle item reordering
const reducer = (state, action) => {
switch (action.type) {
case "REORDER_ITEMS":
return { ...state, items: action.payload };
default:
return state;
}
};
// Main component
const MyComponent = () => {
const [state, dispatch] = useReducer(reducer, { items: initialItems });
return (
<DndListComponent items={state.items} dispatch={dispatch}>
{(item) => <div>{item.content}</div>} {/* Render item content */}
</DndListComponent>
);
};
export default MyComponent;
import React, { useReducer } from "react";
import { itemsReducer } from "@/app/components/Dnd/DndReducer";
import { ItemType } from "@/app/components/Dnd/DndNestList.types";
import DndListComponent from "@/app/components/Dnd/DndNestList";
const initialItems: ItemType[] = [
{
id: 1,
title: "Work Experience",
data: [
{ id: 4, title: "Nested Item 1" },
{ id: 5, title: "Nested Item 2" },
{ id: 6, title: "Nested Item 3" },
],
},
{
id: 2,
title: "Education",
data: [
{ id: 7, title: "Nested Item 4" },
{ id: 8, title: "Nested Item 5" },
{ id: 9, title: "Nested Item 6" },
],
},
];
const Test = () => {
const [items, dispatch] = useReducer(itemsReducer, initialItems);
return (
<DndListComponent items={items} dispatch={dispatch}>
{(item) => (
<div style={{ padding: 8, border: "1px solid gray" }}>
<div>{item.title}</div>
{item.data && (
<DndListComponent
items={item.data}
dispatch={(action) => {
const updatedItems = items.map((i) =>
i.id === item.id ? { ...i, data: action.payload } : i,
);
dispatch({ type: "REORDER_ITEMS", payload: updatedItems });
}}
>
{(nestedItem) => (
<div style={{ padding: 8, border: "1px solid gray" }}>
<div>{nestedItem.title}</div>
</div>
)}
</DndListComponent>
)}
</div>
)}
</DndListComponent>
);
};
export default Test;
Prop | Type | Description |
---|---|---|
items |
ItemType[] |
An array of items I want to display and reorder. Each item must have a unique id . |
children |
(item: ItemType) => React.ReactNode |
A function that returns the content for each item. |
dispatch |
React.Dispatch<ActionType> |
A function to update the state when items are reordered. |
Prop | Type | Description |
---|---|---|
id |
UniqueIdentifier |
A unique identifier for the item. |
title |
string |
The title of the item. |
data |
ItemType[] |
An array of nested items (if any). |
[key: string]: any |
Any | Additional properties can be included as needed. |
Prop | Type | Description |
---|---|---|
type |
"REORDER_ITEMS" |
The action type for reordering items. |
payload |
ItemType[] |
The updated list of items after reordering. |
Prop | Type | Description |
---|---|---|
itemId |
UniqueIdentifier |
The unique identifier for the sortable item. |
content |
React.ReactNode |
The content to render for the sortable item. |
activeId |
UniqueIdentifier,null |
The ID of the currently active (dragging) item. |
isDragging |
boolean |
Indicates if the item is currently being dragged. |
style |
React.CSSProperties |
Custom styles for the item. |
- Reordering: I can drag and drop to reorder items, including nested ones.
- Visual Feedback: The component changes opacity while dragging for a better user experience.
- Restrictions: Dragging is limited to the vertical axis and within the parent element.
I can customize the styles of SortableItem
or modify the component behavior by adjusting the props or styles.
This Drag and Drop List component is especially useful for managing nested lists, making it a valuable addition to my UI toolkit.