Skip to content

How can I have a list of droppables, add a new droppable, and immediately drag things into the new droppable? #970

@merlinstardust

Description

@merlinstardust

I have the following structure in my project. I have an ItemList that contains a top level list of files and folders. Folders can also contain a list of files. With the below setup, I am able to drag files and folders at the top level, drag files into and out of folders, drag files between folders.

Top level drag and drop always works. Folder drag and drop only works for folders/droppables that already exist on page load.

When I add a new folder/droppable, I am unable to drag files into the new folder/droppable.

How can I drag items into folders/droppables that have just been created?

Solutions I've tried:

  • Ensuring the item list is new each time
    • setItems(previousItems => [...previousItems, newItem])
  • Remapping the whole item list when I add an item
    • setItems(previousItems => [...previousItems.map(item => ({...item})), newItem])
  • Using a rerenderKey on DragDropContext
    • setRerenderKey(key = key + 1)

ItemList.tsx

<>
  <DragDropContext key={rerenderKey} onDragEnd={onDragEnd}>
    <Droppable droppableId={"top-level"}>
      {(providedDroppable) => (
        <div {...providedDroppable.droppableProps} ref={providedDroppable.innerRef}>
          {items.map((item, index) => (
            item.type === 'folder' ? <Folder key={item.dragId} index={index} item={item} /> : <File key={item.dragId} index={index} item={item} />
          )}
          {providedDroppable.placeholder as React.ReactNode}
        </div>
      )}
    </Droppable>
  </DragDropContext>

  <AddFolderButton />
</>

Folder.tsx

<>
  <Draggable key={item.dragId} draggableId={item.dragId} index={index}>
    {({ innerRef, draggableProps, dragHandleProps }) => (
      <div ref={innerRef} {...draggableProps} {...dragHandleProps}>
        <FolderLayout item={item} />
      </div>
    )}
  </Draggable>

  
  <Droppable droppableId={`${item.type}-${item.dragId}`}>
    {(providedDroppable) => (
      <div ref={providedDroppable.innerRef} {...providedDroppable.droppableProps}>
        {item.files.length === 0 && <div>Drag files here to add them</div>}
        {item.files.map((file, index) => (<File key={file.dragId} index={index} item={file} />)}
        {providedDroppable.placeholder as React.ReactNode}
      </div>
    )}
  </Droppable>
</>

File.tsx

<Draggable key={item.dragId} draggableId={item.dragId} index={index}>
  {({ innerRef, draggableProps, dragHandleProps }) => (
    <div ref={innerRef} {...draggableProps} {...dragHandleProps}>
      <FileLayout item={item} />
    </div>
  )}
</Draggable>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions