clauderic / dnd-kit

The modern, lightweight, performant, accessible and extensible drag & drop toolkit for React.
http://dndkit.com
MIT License
13.13k stars 651 forks source link

Nested Multiple Containers #735

Open jnavb opened 2 years ago

jnavb commented 2 years ago

I'm trying to do a layout with multiple containers, the direction of the containers would be vertical (Fixed rows, no option to drag) and the item list would be horizontal (horizontalListSortingStrategy), I'll call this component a Panel for now on.

It took me less of an hour to build this Panel with the awesome components helpers from the Storybook, however, users should be able to have Panels as an item of a container (nesting capabilities).

Is this supported? I think I'm really close to a desired result but don't want to deep further if there's a limitation in the library, I'll list the problems I have:

  1. Nested useSortable items move when dragging an item at left/right of its parent

nestedOk

  1. Infinite loop when trying to drag a Panel, not sure if is due the collision strategy. Let me know if I need to open a different issue for this, I think it's related to #552

infinite

You can reproduce both at example-nested-multiple-containers

Second topic is, if example results succesful, are you interested in document this use case? I can offer to refactor the branch and make a PR with such changes, perhaps merging Panel and MultipleContainers components.

Thank you, library is amazing

jnavb commented 2 years ago

I've discovered problem 2 arises because there are useSortables (useDraggable + useDroppable) inside a DragOverlay, as documentation states this is not the intended way:

make sure that the components rendered within the drag overlay do not use the useDraggable hook.

However, at Tree story there are useSortables inside DragOverlay so I don't know if there's a safe way to do it. https://5fc05e08a4a65d0021ae0bf2-polasjgdps.chromatic.com/?path=/story/examples-tree-sortable--all-features

MuhammadHamzaChippa commented 2 years ago

I am getting the same infinite loop error did you figure out the reason why it is happening?

Heilemann commented 1 year ago

I'm getting the same thing, and I cannot for the life of me figure out why :S

theisnygaard commented 1 year ago

@jnavb Did you find a solution to the issue?

diginikkari commented 1 year ago

I'm hitting this infinite loop issue also. Has anyone figured out solution to this?

paulm17 commented 1 year ago

I've been at this issue for a while now, attacking it from several directions. Gave up, but then tried to do it with React-DND which has it's own issues and so came back and tried again.

My use case is nested sortables.

Imgur

Code sandbox: https://codesandbox.io/s/stoic-bohr-fosy2f?file=/src/MultipleContainer.tsx

Note: Previous iteration was using a droppable when a sortable has no children, but now I have changed it to an empty sortable.

I've found out that by dragging an item into another sortable. It will result in an infinite loop of renders of the receiving sortable. Which ultimately ends up in a complete lock of the browser.

To circumvent this, if I check whether the sortable has the item already (post insert) then to do nothing. This resolved the issue. Now I'm able to drag an item from any sortable up and down the nested chain and it won't ever freeze.

I don't think I'm quite done yet, but I'm almost there.

jnavb commented 1 year ago

@Heilemann @theisnygaard @diginikkari @MuhammadHamzaChippa hey, sorry for the delay. I did solve it, there are currently two ways to approach the problem:

A. (Simplest solution) Don't render the dragging element, use a placeholder as the dragoverlay element.

B. In the custom collision strategy filter the droppable containers that are inside the element you are currently dragging. Let's say you are using closestCorners:

closestCorners({
  ...args,
  droppableContainers: args.droppableContainers.filter((container: DroppableContainer) =>
      // remove draggingId and its children
    )
})

hope this helps!