react-beautiful-dnd is a drag and drop library for react, created by Atlassian. It was designed for the focused purpose of handling drag and drop for lists, between lists, and other list related features. They make it clear in the documentation that this was designed for a more specific purpose than other drag and drop libraries that might fit your needs better. Be sure that react-beautiful-dnd meets your needs before moving forward without looking at others such as "react-dnd".
All you need to do, assuming you have yarn or npm installed, go into the terminal and enter the following command:
# yarn yarn add react-beautiful-dnd # npm npm install react-beautiful-dnd --save
You will need a react app to use this library, if you need help on getting started with react please refer to the react docs installation guide here: Installing React
To start giving your application the ability to drag and drop elements, you need to wrap the components you want to give drag and drop in
<DragDropContext />. The documentation recommends that you wrap your entire app in
<DragDropContext />, so let's take a look at that:
This can work inside of your
App.js file or inside of the
index.js file. I chose the
index.js file because it keeps the App component cleaner as you might add things to your application.
The next thing you need to create will be the component(s) where the draggable items can be dropped into. To do this, you will need to import
<Droppable /> and them wrap the area you want to accept draggables inside of it:
There is kind of a lot going on here so let's break it down :
This is the only required prop for
<Droppable />. It
takes a unique string for each
<Droppable /> you have.
Any children you placed inside a
<Droppable /> must be wrapped in a callback function with the arguments "provided" and "snapshot" given.
the provided argument used in the callback function is essentially an object of provided pieces of information that are necessary or helpful in getting the droppable to work. The following are used in this example:
provided.innerRef- This must be attached to the outer most DOM element you have. required
provided.droppableProps- This is an Object within the provided argument that contains information the library uses to function. Belongs on the same element you added
provided.placeholder- This is used to tell the droppable not to shrink down when you are dragging things around, from my understanding. Place this inside of the element you attached
This argument gives you the ability to access the drag state of your elements that can be used for styling and other things
<Draggable /> is used to drag things onto and off of
<Droppable />s. Every
<Draggable /> needs to be inside a
<Droppable />. In order for the user to interact with a
<Draggable />, each one needs a Drag Handle. On top of each one needing a unique
draggableId, each one needs an index to show its position in the list. Additionally, any children of a
<Draggable /> is wrapped in a callback function, same as the
<Droppable />. Here is an example implementation:
This is probably similar to how you would want to implement draggables. Here I have an array of objects representing my data that I want to become draggables. I then created a function to map over this array and create a
<Draggable /> for each object with its own information, index, and
draggableId. I then import this function into my
App.js and place it inside of my
<Droppable />'s callback function:
This results in a working drag and drop within our app!
As you can see, however, when we drag something to a new position in the list, it snaps back to its original position after we are done dragging. This is because we have not yet given our
<DragDropContext /> a
onDragEnd function. This function will handle reordering the list when you drag items to a new position. When you drag something, you get a
result object returned, we can pass this
result to our own drag end function to make it work. First of all, since we are needing to re-render the list after draggables have been moved, we need to set our list to state:
I have restructured my data in this example to better model what your data might look like for practical purposes, here is what it looks like now(the items are nested in a column object, so that you can have multiple columns supported):
With this new data structure, we can create a
onDragEnd function that looks like this:
For reference here is our
The steps in the
onDragEnd function we have made is as follows:
- create the function and pass in three arguments(result, column, setColumn)
- A conditional statement checking the destination value, if it is null(draggable was dragged outside of droppable) return out of the function.
- create variables for the source and destination from our result object (using object destructuring)
- set a column variable equal to the current column we are working in
- copy the items for that column into a new variable
- splice out the dragged item from the original set of items
- splice that item into our copied item list and the destination index
- set the columns state back to what it was, only changing the items list to the new copy
Now, it should be fully functional!
I hope you found this post helpful to your coding journey. This is meant to serve as a truncated version of documentation and youtube so that you might be able to get up and running on your application faster than normal. Thanks for reading!