0

I am using the dnd-kit to have 2 lists of items and I can move items between these lists or sort the list, but while I am dragging an item suddenly it returns to the original position and isDragging is false again. Did someone face this same issue? `

import React, {useState} from 'react';
import {
  useSensors,
  useSensor,
  PointerSensor,
  KeyboardSensor,
  DndContext,
  closestCorners,
  DragEndEvent,
  DragStartEvent,
  DragOverEvent,
  DragOverlay,
  DropAnimation,
  defaultDropAnimation,
  defaultDropAnimationSideEffects,
} from '@dnd-kit/core';
import {sortableKeyboardCoordinates, arrayMove} from '@dnd-kit/sortable';
import colors from 'colors.js';
import {getTaskById} from './utilsTasks';
import {findBoardSectionContainer} from './utilsBoard';
import BoardSection from './BoardSection';
import TaskItem from './TaskItem';
import Header from './Header';
import {Task} from './types';

interface BoardSectionListState {
  available: Task[],
  selected: Task[],
}

interface BoardSectionListProps {
  columns: Task[],
}

const BoardSectionList = (props: BoardSectionListProps) => {
  const [boardSections, setBoardSections] =
    useState<BoardSectionListState>({
      available: [],
      selected: props.columns,
    });

  const [activeTaskId, setActiveTaskId] = useState<null | string>(null);

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

  const handleDragStart = ({active}: DragStartEvent) => {
    setActiveTaskId(active.id as string);
  };

  const handleDragOver = ({active, over}: DragOverEvent) => {
    // Find the containers
    const activeContainer = findBoardSectionContainer(
      boardSections,
      active.id as string
    );
    const overContainer = findBoardSectionContainer(
      boardSections,
      over?.id as string
    );

    if (
      !activeContainer ||
      !overContainer ||
      activeContainer === overContainer
    ) {
      return;
    }

    setBoardSections((boardSection) => {
      const activeItems = boardSection[activeContainer];
      const overItems = boardSection[overContainer];

      // Find the indexes for the items
      const activeIndex = activeItems.findIndex(
        (item) => item.name === active.id
      );
      const overIndex = overItems.findIndex((item) => item.name !== over?.id);

      return {
        ...boardSection,
        [activeContainer]: [
          ...boardSection[activeContainer].filter(
            (item) => item.name !== active.id
          ),
        ],
        [overContainer]: [
          ...boardSection[overContainer].slice(0, overIndex),
          boardSections[activeContainer][activeIndex],
          ...boardSection[overContainer].slice(
            overIndex,
            boardSection[overContainer].length
          ),
        ],
      };
    });
  };

  const handleDragEnd = ({active, over}: DragEndEvent) => {
    const activeContainer = findBoardSectionContainer(
      boardSections,
      active.id as string
    );
    const overContainer = findBoardSectionContainer(
      boardSections,
      over?.id as string
    );

    if (
      !activeContainer ||
      !overContainer ||
      activeContainer !== overContainer
    ) {
      return;
    }

    const activeIndex = boardSections[activeContainer].findIndex(
      (task) => task.name === active.id
    );
    const overIndex = boardSections[overContainer].findIndex(
      (task) => task.name === over?.id
    );
    if (activeIndex !== overIndex) {
      setBoardSections((boardSection) => ({
        ...boardSection,
        [overContainer]: arrayMove(
          boardSection[overContainer],
          activeIndex,
          overIndex
        ),
      }));
    }

    setActiveTaskId(null);
  };

  const filterColumns = (value) => {
    const updatedAvailableColumns = boardSections.available.map(
      (column) => {
        if (value && column.name.toLowerCase().includes(value.toLowerCase())) {
          return {...column, hide: false};
        }
        return value ? {...column, hide: true} : {...column, hide: false};
      }
    );
    setBoardSections({...boardSections, available: [...updatedAvailableColumns]});
  };

  const selectAll = () => {
    setBoardSections({selected: [...props.columns], available: []});
  };
  const unSelectAll = () => {
    setBoardSections({available: [...props.columns], selected: []});
  };

  const dropAnimation: DropAnimation = {
   ...defaultDropAnimation,
  };

  const task = activeTaskId ? getTaskById(props.columns, activeTaskId) : null;
  return (
    <div style={{height: '90%'}}>
      <Header filterColumns={filterColumns} selectAll={selectAll}  unSelectAll={unSelectAll}/>
      <DndContext
        sensors={sensors}
        collisionDetection={closestCorners}
        onDragStart={handleDragStart}
        onDragOver={handleDragOver}
        onDragEnd={handleDragEnd}
      >
        <div style={{display: 'flex', flexDirection: 'row', height: '79%'}}>
          <BoardSection
            key="available"
            borderRight={{borderRight: `1px ${colors.gray} solid`}}
            id="available"
            tasks={boardSections.available} />
          <BoardSection
            key="selected"
            id="selected"
            tasks={boardSections.selected} />
          <DragOverlay dropAnimation={dropAnimation}>
            {task ? <TaskItem task={task} isDragging /> : null}
          </DragOverlay>
        </div>
      </DndContext>
    </div>
  );
};

export default BoardSectionList;

import React, {useMemo} from 'react';
import {map} from 'lodash';
import {useDroppable} from '@dnd-kit/core';
import {
  SortableContext,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable';

import {Task} from './types';
import TaskItem from './TaskItem';
import SortableTaskItem from './SortableTaskItem';

type BoardSectionProps = {
  id: string;
  tasks: Task[];
  borderRight?: Object,
};

const BoardSection = ({id, tasks, borderRight}: BoardSectionProps) => {
  const  {setNodeRef} = useDroppable({
    id,
  });
  const items = useMemo(() => (tasks.map(item => item.name)), [map(tasks, 'name')]);
  return (
    <div style={{boxSizing: 'border-box', padding: '10px', maxWidth: '50%', flexBasis: '50%', height: '100%', overflow: 'auto', ...borderRight}}>
      <SortableContext
        id={id}
        items={items}
        strategy={verticalListSortingStrategy}
      >
        <div ref={setNodeRef}>
          {tasks.map((task) => {
            return !task.hide ? (
              <div key={task.name}>
                <SortableTaskItem id={task.name}>
                  <TaskItem task={task} />
                </SortableTaskItem>
              </div>
            ) : null;
          })}
        </div>
      </SortableContext>
    </div>
  );
};

export default BoardSection;

import React from 'react';
import {useSortable} from '@dnd-kit/sortable';
import {CSS} from '@dnd-kit/utilities';

type SortableTaskItemProps = {
  children: React.ReactElement;
  id: string;
};

const SortableTaskItem = ({children, id}: SortableTaskItemProps) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({id});

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? .3 : 1,
  };
  return (
    <div ref={setNodeRef} style={style}>
      {children && React.cloneElement(children, {attributes, listeners})}
    </div>
  );
};

export default SortableTaskItem;

I already check all the documentation and everything seems correct, so I am not sure what is going on

0 Answers0