Getting started with React Dnd-Kit
Tags: dndkit, react, dragndrop, javascript
Published: 2022-07-16 14:58:39

In this article we are going to use one of the drag n drop library for react. There are few good drag n drop libraries for react like [react-dnd](https://react-dnd.github.io/react-dnd/), [dnd-kit](https://dndkit.com/) & [react-beautiful-dnd](https://github.com/atlassian/react-beautiful-dnd).

We are going to look into dnd-kit today reason behind using this library was that it supports a lot of usecase, availability of hooks, being the light-weight etc.

To start with lets create an react app with create-react-app & install the necessary libraries with it 

`npx create-react-app react-dndkit-eg`

`npm install --save @dnd-kit/core @dnd-kit/sortable`

@dntkit/core & @dndkit/sortable these are the two libraries which we will be requiring to support basic dragndrop functionalities, library also provides support various other features with other libs like `@dnd-kit/utilities`, `@dnd-kit/modifiers `, `@dnd-kit/accessibility` more details about each of these can be read on their website.

To start with we will be creating component which will be wrapping our draggable/sortable component, the whole idea of dnd in simple terms it to have a container where your item can be dragged into or moved across so the code regarding the component will somewhat look like this [sortable-component-complete-code](https://github.com/shubhadip/react-dndkit-eg/blob/master/src/components/sortableItem.js)

```
...
# e.g code snippet
export function SortableItem(props) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({id: props.id}); 
  
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };
  
  if(props.handle) {
    return (<div ref={setNodeRef} style={style} {...attributes} className={'pos-relative'}>
      {
        props.handle ? 
        <span className='dragHandleClass' {...listeners}>
          # some svg/img/htmlelement
        </span>
        : null
      }
      {props.children}
    </div>)
  }
  
  return (
    <div ref={setNodeRef} style={style} {...attributes}   {...listeners} className={'pos-relative'}>
      {props.children}
    </div>
  );
}
...
```
the above code acts as wrapper for the component that needs to dragged/sorted, we will talk about the handle prop later in the article, the `id` prop is passed to useSortable hook so that every item can be uniquely identified.

Now lets create a component which will be having multiple items that can be sorted or dragged on, to create a container we would need DndContext & SortableContext so that the grid & row elements can be moved/sorted across.

DndContext takes a fews props some of them are sensors, collisionDetection etc these also includes functions like handleDragStart & handleDragEnd these are the functions which can be use before & after the whole dragndrop interaction. 

`Similarly SortableContext takes few props , here we will have to pass items which should be an array on uniqueIds & this should be same as that we have passed to sortableItem above.`

The code of the context should be similar to this [sortable-context-complete-code](https://github.com/shubhadip/react-dndkit-eg/blob/master/src/components/gridEg/index.js)
```
...
# e.g sortable context/container

<DndContext 
          id={'grid-dnd-basic'}
          onDragEnd={handleDragEnd}
          sensors={sensors}
          collisionDetection={closestCenter}
        >
            <SortableContext 
              id={'grid-sort-contextbasic'}
              items={items.map((i) => i?.id)}
            >
              {items.map(value => {
                
                return (
                  <SortableItem handle={true} key={value?.id} id={value?.id} >
# sortableItem Content
                  </SortableItem>
                )
              })}
            </SortableContext>
          </DndContext>
...

```

At this point we are done with our component setup regarding drag n drop, now we will have to add handler to functions like handleDragStart/handleDragEnd, code for these are almost similar to what the documentation of dnd-kit provides only change is the items property that is passed to the handler function
```

  function handleDragEnd(event) {
    const {active, over} = event;
    
    if (active.id !== over.id) {
      setItems((items) => {
        const oldIndex = (items.map(i => i.id)).indexOf(active.id);
        const newIndex = (items.map(i => i.id)).indexOf(over.id);
        
        return arrayMove(items, oldIndex, newIndex);
      });
    }
  }
```
in the above code you can see we are using map function to pass only ids for the indexOf function as everything is mapped to uniqueId that is passed to sortableItem & sortableContext.
So we are almost ready with our dnd-kit implementation for sorting using dndContext & sortableContext. 

`Now lets visit the handle prop that we have used earlier in our sortableItem, so we can see useSortable provides a listeners now if we want to drag the item using some handler and not the actual item then we can use handle prop to apply listener to the drag-handler directly, in this way we will be able to drag via some handler and not he actual item`

```
# e.g handle implementation
...
  if(props.handle) {
    return (<div ref={setNodeRef} style={style} {...attributes} className={'pos-relative'}>
      {
        props.handle ? 
        <span className='dragHandleClass' {...listeners}>
          # svg/image/html-element
        </span>
        : null
      }
      {props.children}
    </div>)
  }
  ...
```

Now lets talk about the [sensors](https://docs.dndkit.com/api-documentation/sensors#built-in-sensors) in the whole e.g we will be using the basic sensor implementation in the doc  which looks similar to this 

```
  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );
```

Now these use sensor takes second parameters as object which also has a property `activationConstraint`, now this can be used to activate the sensor only after some pixel movements [code](https://github.com/shubhadip/react-dndkit-eg/blob/master/src/components/gridSwapEg/index.js#L29).

```
  const sensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates,
    })
  );
```

`The scenarios where this can be used is when you have an click listener to you sortableItem & you don't use drag-handle, so that we can uniquely identify click & drag events, without this constraint event click will be treated as drag events & our drag-handler functions like onDragEnd & onDragStart will be triggered.`

this article mostly covers topics related to [dndContext](https://docs.dndkit.com/api-documentation/context-provider) and [sortable](https://docs.dndkit.com/presets/sortable) preset more about the same can be read at dnd-kit website.

The code related to the article is present in the [GithubLink](https://github.com/shubhadip/react-dndkit-eg) & [gh-pages](https://shubhadip.github.io/react-dndkit-eg/)