Getting Started with "React-beautiful-dnd" using functional components
Tags: react, tutorial, webdev
Published: 2022-01-02 23:12:16


##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
```
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](https://beta.reactjs.org/learn/installation) 

##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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2kn1far3typudva4hjs.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/odlkvoz7iyyytfxgew9t.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb9c2fpx0n7ztmymi5pc.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rpa2dgm8i44orsg7gzcu.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g6vtf0lz5vrq7jasrto3.png)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o0meu5u8rdnop5kqxu88.gif)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2pqhjua0sgwe4mzngpsb.png)

**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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lvha8acx6rxjw16mvjjx.png)

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


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rj0bhuze5yzc1dw7qf4u.png)

For reference here is our `result` object: 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6my3ny7cv5xqsp5ojia3.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zol73i0kbaxd31upiwk1.gif)

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](https://github.com/atlassian/react-beautiful-dnd)
[Youtube Video] (https://www.youtube.com/watch?v=Vqa9NMzF3wc)