DEV Community

Cover image for Getting Started with "React-beautiful-dnd" using functional components
Kyle
Kyle

Posted on

Getting Started with "React-beautiful-dnd" using functional components

What is "react-beautiful-dnd" ?

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".

Installing "react-beautiful-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
Enter fullscreen mode Exit fullscreen mode

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

Getting Started once you have it installed:

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:
Image description

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.

<Droppable />

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:

Image description

There is kind of a lot going on here so let's break it down :

droppableId
This is the only required prop for <Droppable />. It
takes a unique string for each <Droppable /> you have.

Droppable Children

Any children you placed inside a <Droppable /> must be wrapped in a callback function with the arguments "provided" and "snapshot" given.

provided

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 innerRef required
  • 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 innerRef to

snapshot

This argument gives you the ability to access the drag state of your elements that can be used for styling and other things

<Draggable />

A <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:

Image description
Image description

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:

Image description

This results in a working drag and drop within our app!

Image description

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:

Image description

Side Note
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):

New Data to support having more than one Column

With this new data structure, we can create a onDragEnd function that looks like this:

Image description

For reference here is our result object:

Image description

The steps in the onDragEnd function we have made is as follows:

  1. create the function and pass in three arguments(result, column, setColumn)
  2. A conditional statement checking the destination value, if it is null(draggable was dragged outside of droppable) return out of the function.
  3. create variables for the source and destination from our result object (using object destructuring)
  4. set a column variable equal to the current column we are working in
  5. copy the items for that column into a new variable
  6. splice out the dragged item from the original set of items
  7. splice that item into our copied item list and the destination index
  8. set the columns state back to what it was, only changing the items list to the new copy

Now, it should be fully functional!

Image description

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!

Sources:
Github
Youtube Video

Top comments (0)