Setting up react-beautiful-dnd in your React application
4 min readMar 11, 2023
react-beautiful-dnd is a React library to apply beautiful and accessible drag and drop for list elements.
Installation
- Open terminal with your project directory and install
react-beautiful-dnd
# yarn
$ yarn add react-beautiful-dnd
# npm
$ npm install react-beautiful-dnd
Setting up in Project
- For this tutorial, I’ll be applying react-beautiful-dnd in a simple note taking react project like below:
- The above page is rendered with the following component:
import useFetch from "../config/useFetch";
import NoteCard from "../components/NoteCard";
const Home = () => {
const { notes, setNotes, fetchError } = useFetch();
return (
<div className="page">
{fetchError && <h2>{fetchError}</h2>}
{notes && (
<div className="notes">
<div className="notes-grid">
{notes.length === 0 ? (
<div className="empty">
<h1>No Notes Yet</h1>
</div>
) : (
notes.map((note, index) => (
<NoteCard note={note} index={index} />
)
)}
</div>
</div>
)}
</div>
);
};
export default Home;
- Start with importing
DragDropContext
,Draggable
andDroppable
fromreact-beautiful-dnd
in your component file where you want to apply drag and drop facility in your react project.
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd'
- Visual representation how these three components work is given below:
- Use the
<DragDropContext>
tag to enclose thediv
containing all note elements (the area where all drag and drops are intended to occur). - Now use the
<Droppable>
tag inside the<DragDropContext>
and use a JavaScript function with an argument ofprovided
which returns the samediv
containing the note elements. - Give the props
{…provided.droppableProps}
andref={provided.innerRef}
to the top leveldiv
which is inside the function. - Before closing the top level
div
tag which is inside function, add a value{provided.placeholder}
at the end. - Also make sure to provide a
droppableId
to theDroppable
component.
In my case, mydroppableId
isnotes
.
import useFetch from "../config/useFetch";
import NoteCard from "../components/NoteCard";
import {DragDropContext, Draggable, Droppable} from 'react-beautiful-dnd';
const Home = () => {
const { notes, setNotes, fetchError } = useFetch();
return (
<div className="page">
{fetchError && <h2>{fetchError}</h2>}
{notes && (
<div className="notes">
<DragDropContext>
<Droppable droppableId="notes">
{(provided) => (
<div
className="notes-grid"
{...provided.droppableProps}
ref={provided.innerRef}
>
{notes.length === 0 ? (
<div className="empty">
<h1>No Notes Yet</h1>
</div>
) : (
notes.map((note, index) => (
<NoteCard note={note} index={index} />
))
)}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
)}
</div>
);
};
export default Home;
- Now we’ll use the
<Draggable>
tag to wrap our each div which is going to be draggable. In my case I’ll wrap my<NoteCard>
component inside map function as my every note is to be dragged and dropped. - Inside
<Draggable>
tag open a JavaScript function with argumentprovided
and return the component that is supposed to be dragged.
notes.map((note, index) => (
<Draggable key={note.id} draggableId={note.id?.toString()} index={index}>
{(provided) => (
<div
{...provided.dragHandleProps}
{...provided.draggableProps}
ref={provided.innerRef}
>
<NoteCard note={note} index={index} />
</div>
)}
</Draggable>
))
- Because I’m using a component inside the
<Draggable>
tag, the draggable tag’s props cannot be used in it. We’ll need a parentdiv
to wrap our<NoteCard>
component and serve as our top level div. - We will then pass our draggable props
{…provided.dragHandleProps}
,{…provided.draggableProps}
andref={provided.innerRef}
in our top level div tag. Also give a uniquedraggableId
to<Draggable>
tag. - You should now be able to drag and drop components in your project, but after dropping the component, its state does not change and it returns to its original position.
Managing the state on drag and drop
- To manage the state of components when dropping them, we have to create a function which will save the new order of the mapped array.
- We’ll create a function
handleOnDragEnd
which have an argumentresult
and this function will be passed in<DragDropContext>
as a prop.
...
<DragDropContext onDragEnd={ handleOnDragEnd }>
...
- The
result
argument is the object that shows some data about the component which is dragged and dropped and also includes its source index and destination index.
You can try logging it out in console for better understanding
const handleOnDragEnd = (result) => {
if(!result.destination){
return
}
const items = Array.from(notes);
const [reorderedNotes] = items.splice(result.source?.index, 1);
items.splice(result.destination?.index, 0, reorderedNotes);
setNotes(items);
}
- The
handleOnDragEnd
function above gets the source index of the dragged item and puts it in the destination index and finally updates the state. - If we try to drop the item outside the droppable area, then the destination index will be null and function will simply return.
- Our final code snippet would be as follows:
- Now our home page would look like this:
Conclusion
That’s how you can setup react-beautiful-dnd in your React application.