Building Kanban with dnd kit and React

Are you a developer looking for an alternative to react-beautiful-dnd? Look no further! The DND toolkit is here, and we'll discuss how to use it in this walkthrough guide.

D-kit as an alternative to React-Beautiful-DND

One of the most popular UI patterns for designing web interfaces is the drag and drop pattern. It is an easy-to-use and intuitive mode that can be included in projects and is most commonly used for processes such as uploading files and reordering or moving projects.

There are several packages that make implementing drag and drop functionality easy, a popular choice among React developers is react-beautiful-dnd.

Unfortunately, it is no longer maintained and there are no future developments planned. This leaves developers like me looking for a solid alternative, and gives me yet another reason not to like Atlassian (the first being Jira!

Enter the DND kit.

What is the dnd suite?

DND Kit is the new "kit" on the block (blame the creators for this joke), and it looks promising for those looking for a React-beautiful-DND alternative.

In this tutorial, how to install the Windows 11 computer sound card driver? Teach you five easy ways to do it We'll create a basic Kanban board while learning about the dnd suite and its capabilities.

Here's an image of what the board will look like when we're done:

Start using the dnd suite

We will first use Create React App to set up a Windows 11 how to see the computer graphics card? A React project. For simplicity, we'll be using the Chakra UI component library because it's easy to set up and use.

To create and setup a React project, run the following commands:

npx create-react-app react-kanban-app --template @chakra-ui   # create project
cd react-kanban-app   # move into the project directory
​
# If you prefer TS over JS and yarn over npm
npx create-react-app react-kanban-app --template @chakra-ui/typescript
yarn create react-app react-kanban-app --template @chakra-ui
yarn create react-app react-kanban-app --template @chakra-ui/typescript

This will create a folder named . Use the command line cd to the project directory and run: react-kanban-app

npm run start

This will start the application on port 3000. What should I do if the chrome browser takes up too much memory? Solve the problem of Chrome eating memory problems Open it in the browser, you will see the following screen: localhost:3000

Install dnd-kit/core

Now that we have a base project set up, let's start by installing dnd kit; the lightweight, performant, and extensible drag-and-drop kit for React that we'll be using today.

To install the package, run:

npm install @dnd-kit/core
​
# If you run into peer dependencies issues (esp. npm 7+)
npm install --legacy-peer-deps @dnd-kit/core

This command will install the package from dnd-kit. core

The package comes with what to do if the QR code for WhatsApp computer version is not displayed in the React application ? 9 building blocks needed to quickly tackle the tutorial's drag-and-drop functionality. The package comes with , and core components. core DndContextDraggable``Droppable

Besides that, it comes with a component that improves the user experience with a smoother look - we'll cover the core components in more detail later in this article. Drag Overlay

For more advanced use cases, we can also install other packages provided by dnd kit.

Modifier

This package comes with useful modifiers that can be used to change the behavior of core components.

Here are some main functions of modifiers:

  • Limit movement to a single axis (horizontal or vertical)

  • Constrains motion to window or draggable item's parent element

  • Align draggable items to grid

  • Create custom modifiers

presets (sortable presets)

The dnd-kit toolkit comes with a sortable preset. What should I do if the call history of this Android phone does not display? 10 Ways to Fix It presets for building sortable drag and drop interfaces in React.

For this tutorial, we'll stick to the core package, so before we get started, let's take a closer look at it.

Building blocks of the dnd suite

DndContext

This is the root component for our drag and drop functionality, inside which all other blocks are nested.

This component accepts about a dozen props that help modify behavior or run code when certain events occur.

For the purposes of this tutorial, we'll be using and props. collisionDetection``onDragEnd

Watch out for more info on other props.

draggable

The core package exports hooks that can be used in our React components to make them draggable (more on that later). useDraggable

//exampleDraggable.jsx
import {useDraggable} from "@dnd-kit/core"
import {CSS} from "@dnd-kit/utilities"
​
export const MyDraggableComponent = () => {
const {attributes, listeners, setNodeRef, transfrom} = useDraggable({
  id: 'draggable-1',
  data: {
    ....
    parent: 'ToDo',
    title: 'Complete blogpost.'
    ....
  }
  return <div 
          {...attributes} 
          {...listeners} 
          ref={setNodeRef} 
          styles={
  
  {transfrom: CSS.Translate.toString(transform) }}>Drag Me!</div>
})

dripping

Just like hooks, we can use hooks to make our React components droppable targets. useDraggable``useDroppable


//exampleDroppable.jsx
import {useDroppable} from "@dnd-kit/core"
​
export const MyDroppableComponent = () => {
  const {setNodeRef} = useDroppable({
    id: 'droppable-1'
  })
​
  return <div ref={setNodeRef}> Drop on me! </div>
}

sensor

Sensors are different input methods that can be used to initiate dragging of draggable items.

We can use some built-in sensors:

  • pointer

  • keyboard

  • touch

  • mouse

The default is and sensor. If you want to use other sensors, you can do this by initializing the sensor and then passing it to . DndContext PointerKeyboard``DndContext

//sensors.jsx
import {MouseSensor, TouchSensor, useSensor} from '@dnd-kit/core';
​
export const DragDropContainer = () => {
​
  const mouseSensor = useSensor(MouseSensor); // Initialize mouse sensor
  const touchSensor = useSensor(TouchSensor); // Initialize touch sensor
  const sensors = useSensors(mouseSensor, touchSensor)
​
  return (<DndContext sensors={sensors}>.....</DndContext>) // Pass the 2 sensors
}

Now that we've covered the basics, we can start building Kanban boards with dnd kit, so let's jump right into it.

Shown above is the component breakdown of the Kanban board we will build.

We will explore three main components today:

  • KanbanCard: a draggable kanban item that can be dragged and dropped into the droppable area

  • KanbanLane: a placeable droppable area KanbanCard

  • KanbanBoard: The component that holds everything together

KanbanCard element

Let's start with the component: KanbanCard

// KanbanCard.tsx
import { Flex, Text } from "@chakra-ui/react";
import { useDraggable } from "@dnd-kit/core";
import { CSS } from "@dnd-kit/utilities";
​
const KanbanCard = ({
  title,
  index,
  parent,
}: {
  title: string;
  index: number;
  parent: string;
}) => {
  const { attributes, listeners, setNodeRef, transform } = useDraggable({
    id: title,
    data: {
      title,
      index,
      parent,
    },
  });
  const style = {
    transform: CSS.Translate.toString(transform),
  };
  return (
    <Flex
      padding="3"
      backgroundColor="white"
      margin="2"
      borderRadius="8"
      border="2px solid gray.500"
      boxShadow="0px 0px 5px 2px #2121213b"
      transform={style.transform}
      {...listeners}
      {...attributes}
      ref={setNodeRef}
    >
      <Text>{title}</Text>
    </Flex>
  );
};

There are a few things to note here, which I'll highlight below.

The component requires three props:

  • title: card title

  • index: the index of the card in the current channel

  • parent: the name of the lane where the card is currently located

To make a component draggable we have to use hooks. In the above example of Quzhi Notes site map , we need to pass something as a parameter: useDraggable

  • id: used to identify DndContext

  • data: data that can be used in the event handler

The hook also returns a number of things we have to take into account:

  • attributes: Accessibility attributes that need to be added to the draggable DOM node

  • listeners: many event handlers are required for dragging to work

  • setNodeRef: function used by dnd-kit to track DOM nodes

  • transform: An object that holds the position and scales the value of the draggable element

Finally, to update the component visually, we must update the card's CSS properties. In order to get the card position, we need to pass the converted value returned by the hook to the helper function provided by dnd-kit. transform``useDraggable

KanbanLane element

Now, let's look at the component: KanbanLane

// KanbanLane.tsx
import { Flex, Text } from "@chakra-ui/react";
import { useDroppable } from "@dnd-kit/core";
​
interface KanbanLaneProps {
  title: string;
  items: Cards[];
}
​
export default function KanbanLane({ title, items }: KanbanLaneProps) {
  const { setNodeRef } = useDroppable({
    id: title,
  });
  return (
    <Flex flex="3" padding="5" flexDirection="column" minH="10rem">
      <Text fontWeight="bold">{title}</Text>
      <Flex
        ref={setNodeRef}
        backgroundColor="gray.200"
        borderRadius="8"
        flex="1"
        padding="2"
        flexDirection="column"
      >
        {items.map(({ title: cardTitle }, key) => (
          <KanbanCard title={cardTitle} key={key} index={key} parent={title} />
        ))}
      </Flex>
    </Flex>
  );
}

This is a very lean component because all it does is render multiple components. One thing to note is that it uses hooks, which makes it a droppable area. KanbanCard``useDroppable

We need to pass in the unique .id``DndContext in a

KanbanBoard element

Finally, let's take a closer look at the component that ties it all together: KanbanBoard

// KanbanBoard.tsx
import { DndContext, rectIntersection } from "@dnd-kit/core";
import KanbanLane from "./KanbanLane";
import AddCard from "./AddCard";
import { Flex } from "@chakra-ui/react";
import { useState } from "react";
import { Cards } from "./types";
export default function KanbanBoard() {
  const [todoItems, setTodoItems] = useState<Array<Cards>>([]);
  const [doneItems, setDoneItems] = useState<Array<Cards>>([]);
  const [inProgressItems, setInProgressItems] = useState<Array<Cards>>([]);
  const [uItems, setuItems] = useState<Array<Cards>>([]);
  const addNewCard = (title: string) => {
    setuItems([...uItems, { title }]);
  };
  return (
    <DndContext
      collisionDetection={rectIntersection}
      onDragEnd={(e) => {
        const container = e.over?.id;
        const title = e.active.data.current?.title ?? "";
        const index = e.active.data.current?.index ?? 0;
        const parent = e.active.data.current?.parent ?? "ToDo";
        if (container === "ToDo") {
          setTodoItems([...todoItems, { title }]);
        } else if (container === "Done") {
          setDoneItems([...doneItems, { title }]);
        } else if (container === "Unassigned") {
          setuItems([...uItems, { title }]);
        } else {
          setInProgressItems([...inProgressItems, { title }]);
        }
        if (parent === "ToDo") {
          setTodoItems([
            ...todoItems.slice(0, index),
            ...todoItems.slice(index + 1),
          ]);
        } else if (parent === "Done") {
          setDoneItems([
            ...doneItems.slice(0, index),
            ...doneItems.slice(index + 1),
          ]);
        } else if (parent === "Unassigned") {
          setuItems([...uItems.slice(0, index), ...uItems.slice(index + 1)]);
        } else {
          setInProgressItems([
            ...inProgressItems.slice(0, index),
            ...inProgressItems.slice(index + 1),
          ]);
        }
      }}
    >
      <Flex flexDirection="column">
        <AddCard addCard={addNewCard} />
        <Flex flex="3">
          <KanbanLane title="ToDo" items={todoItems} />
          <KanbanLane title="In Progress" items={inProgressItems} />
          <KanbanLane title="Done" items={doneItems} />
          <KanbanLane title="Unassigned" items={uItems} />
        </Flex>
      </Flex>
    </DndContext>
  );

There's a lot going on here; let's go over them one by one.

First, the board has four channels: , , and . ToDo In ProgressDone``Unassigned

Second, the component is just a textbox with a button on it. When the button is clicked, a card with the title specified in the text box will be created and added to the channel. <AddCard/>``Unassigned

The DndContext is located at the root of the component, and we need to pass it two important props:

  • collisionDetection: This determines which method is used to detect collisions between draggable and droppable components

  • onDragEnd

    : This is an event handler that runs every time we stop dragging the draggable. In the event handler:

    • We identify the lane the card is in and remove it

    • We determine which lane the card fell on and add it to that lane

In the end, this is what it looks like

in conclusion

While react-beautiful-dnd is not actively maintained, it is more mature and has a large community around it. Because of this, convincing people to jump ship can certainly be challenging. It also has some advanced features like support for multiple drags, virtual list support and SSR which the dnd suite doesn't provide out of the box.

However, I feel that dnd kit has the potential to achieve the same functionality as react-beautiful-dnd and even go beyond that. Interested people can help make this happen by fixing issues and opening PRs!

Guess you like

Origin blog.csdn.net/weixin_47967031/article/details/132706373