React beautiful DND - I get "Unable to find draggable with id: 1"
Asked Answered
C

21

49

In the code below the UI renders two "Column" components and each column contains two draggable elements called "Tasks". When the user drags a "Task" between columns the code works - up to a point. When the user continuously drags the task components around eventually they will stop dragging and the user gets an error that says:

Unable to find draggable with id: X

I don't know why this happens nor how to fix it.

Note: I am assuming the way the library works is when you drag elements you need to reorder and update your state in the onDragEnd function.

Here is my code:

app.js

import React,{useState} from 'react';
import {DragDropContext} from 'react-beautiful-dnd';
import helper from './helper_functions'

import Column from './Components/Column';

function App() {

  let initialState =   [
    {
      groupName:"Today",
      tasks:[
          {id:"1", title:"Test-1"},
          {id:"2", title:"Test-2"}
        ]
    },
    {
      groupName:"Tomorrow", 
      tasks:[
          {id:"3", title:"Test-3"},
          {id:"4", title:"Test-4"}
        ]
    },
  ]


  const [taskList, setTasks] = useState(initialState)

  function onDragEnd(val){

     let result = helper.reorder(val.source,val.destination,taskList);
     setTasks(result)
  }

  return (
    <DragDropContext onDragEnd={onDragEnd}>
       <Column droppableId="Today" list= {taskList[0].tasks} type="TASK"/>
       <Column droppableId ="Tomorrow" list = {taskList[1].tasks} type="TASK"/>
       <div> context hello world </div>
    </DragDropContext>
  );
}

export default App;

src/helper_functions

export default {
    reorder:function(source,destination,taskDataArr){

     let taskData = [...taskDataArr]

 //     //_____________________________________________________________Source data
    let sourceGroupIndex = taskData.findIndex((val, index) => {                // iterate and find "Today" (or other) index in list data
        return val.groupName === source.droppableId
    });

    let draggedTask = taskData[sourceGroupIndex].tasks.find((val, index) => {  // Get specific task object based on index
        return source.index === index
    }); // dragged object

    let sourceListCopyWithElementRemoved = taskData[sourceGroupIndex].tasks.filter((val, index) => {
        return index !== source.index // removes dragged element from array
    });

    // //__________________________________________________________________Destination data

    let destinationGroupIndex = taskData.findIndex((val, index) => {  // iterate and find "Tomorrow" (or other) index in list data
        return val.groupName === destination.droppableId
    });


    taskData[destinationGroupIndex].tasks.splice(destination.index, 0, draggedTask); // insert dragged item to new place
    taskData[sourceGroupIndex].tasks = sourceListCopyWithElementRemoved

    return taskData

  }


}

src/Components/Column

import React from 'react';
import {Droppable} from 'react-beautiful-dnd';
import Task from "../../Components/Task"

function Column(props){
   const { classes, droppableId, list, type} = props;

   let style = {
    backgroundColor:"orange",
    height:"300px",
    width:"400px",
    margin:"100px"

   }

   console.log(list)



    return (

       <Droppable droppableId = {droppableId} type={type}>
       {provided => (

          <div {...provided.droppableProps} ref={provided.innerRef} style={style}>
          <h2>{droppableId}</h2>

            {list.map((val,index)=>{
               return <Task id={val.id} key={index} index={index} title={val.title}/>
            })}

           {provided.placeholder}
          </div>
        )
       }
       </Droppable>
    )
}

export default Column

src/Components/Task

import React from 'react';
import {Draggable} from 'react-beautiful-dnd';



function Task(props){
    const { classes, id, index,title } = props;
    let style = {
    backgroundColor:"red",


   }

    return (
       <Draggable draggableId ={id} index={index} type="TASK">

         {(provided) => (
            <div
              ref={provided.innerRef}
              {...provided.draggableProps}
              {...provided.dragHandleProps}
            >
              <h4 style={style}>{title}</h4>
            </div>
        )}

       </Draggable>
    )
}

export default Task
Casualty answered 2/2, 2020 at 19:25 Comment(4)
Dear bro @William, For such a case like your question. it is better to put a reproduction of your project on GitHub or GitLab and leave its link here, someone like me checks out the project and finds the bug. Literally, I ask you this.Sexagesimal
Okay, thanks for the polite response. I'll do that after work.Casualty
@Casualty can you provide some fiddle for this?Surmullet
Looks like someone below created a codesandboxCasualty
M
84

There are a few issues with your code:

  1. Error Unable to find draggable with id: X

In the Column component you used index as a key for the tasks. I think this is what causes this error.

Using the task id as key, in Column, makes this error go away.

  1. reorder has some issues:
    • it removes a task when dropped in the same column
    • raises an error when a task is dropped outside the columns

I had a bit of fun with you code and tried another way to reorder. This way of reordering might come in handy if you ever add a more columns - there is still room for improvements.

Hope it helps!

Merissameristem answered 6/2, 2020 at 10:35 Comment(3)
Using ID that is the same for draggableId prop instead of index for key prop solved my problemAdvent
@SyedAqeel Thanks, man!! sometimes comments are better than answers.Atomism
I had key as index instead of id - thank you ;-)Tapioca
B
86

If you are getting this error on React 18

Unable to find draggable with id: 

Try removing StrictMode

Banger answered 23/5, 2022 at 21:56 Comment(8)
why the strict mode is affect this behavior ?Warmedover
Seconded. This works for me, but I'd like to keep strict mode-- what's happening here?Georgiannegeorgic
there is drop-in replacement that fixed this issue here: github.com/hello-pangea/dndYockey
Rather than replace the whole library or turn off Strict Mode, try using this solution: github.com/atlassian/react-beautiful-dnd/issues/…Rachellerachis
@MarcinHubert I believe that fork is a good enough solution that it warrants it's own answer. I would upvote it if it were.Malik
this code helped me to solve a problem: github.com/atlassian/react-beautiful-dnd/issues/…Craftsman
Wow. This solved my problem as well. I am on Next 13Cami
I'm using hello-pangea/dnd and the problem still happens, don't know if it's my faut. Edit: was my fault, I forgot to add the key to my Draggable , now the everything works fine.Doering
M
84

There are a few issues with your code:

  1. Error Unable to find draggable with id: X

In the Column component you used index as a key for the tasks. I think this is what causes this error.

Using the task id as key, in Column, makes this error go away.

  1. reorder has some issues:
    • it removes a task when dropped in the same column
    • raises an error when a task is dropped outside the columns

I had a bit of fun with you code and tried another way to reorder. This way of reordering might come in handy if you ever add a more columns - there is still room for improvements.

Hope it helps!

Merissameristem answered 6/2, 2020 at 10:35 Comment(3)
Using ID that is the same for draggableId prop instead of index for key prop solved my problemAdvent
@SyedAqeel Thanks, man!! sometimes comments are better than answers.Atomism
I had key as index instead of id - thank you ;-)Tapioca
L
16

Not for this case, but For every one - check provided.draggableProps not provided.dropableProps

 <Draggable draggableId ={id} index={index} type="TASK">

         {(provided) => (
            <div
              ref={provided.innerRef}
              {...provided.draggableProps}
              {...provided.dragHandleProps}
            >
              <h4 style={style}>{title}</h4>
            </div>
        )}
</Draggable>

RBD try find node by provided.draggableProps. Missing this props got error: Unable to find draggable with id: X

Lousy answered 9/6, 2020 at 11:45 Comment(0)
H
14

I had a similar issue, I was mapping through multiple draggable and had missed the key prop, Adding the key to Draggable fixed the issue for me

{tasks.map((t, index) => (
  <Draggable
    draggableId={t._id}
    index={index}
    key={t._id} >
     ....
  </Draggable>
}
Hickie answered 30/9, 2021 at 13:5 Comment(3)
Thanks! I added key={task.id} for my Draggable wrapper and also added key={column.id} to my Droppable wrapper and it works out of the box!Venerable
Works like a charm. Thank you. Just pass your id instead of the index and the issue will be fixedBenjy
@AgostinhoNeto solution works for me ,the issue was with droppable key , ThanksSharleensharlene
B
13

For Error:

Unable to find draggable with id: X

  1. Remove Strict mode in React js.
  2. If you are using Next.js you can find the strict mode in next.config.js file

For Error:

Invariant failed: Draggable[id: 1]: Unable to find drag handle do the following

{process.browser && (
        <section>
          <DragDropContext onDragEnd={onDragEnd}>
                     //Your code with droppable and draggable
           </DragDropContext>
        </section>
)}

Related issue

Bo answered 18/6, 2022 at 1:56 Comment(1)
It worked but now I am getting hydration error in Next.jsRinged
U
11

The library is not being maintained any longer. I switch to the fork:

https://github.com/hello-pangea/dnd

And all issues were resolved.

Undercover answered 29/7, 2023 at 10:51 Comment(2)
Thank you so much for this. Was tearing my hair out trying to get the unmaintained version to work!Motive
All the tutorials worked perfectly in a sandbox but failed miserably on my local machine. Your tip saved me. Thanks a lot for thisTerisateriyaki
R
9

Removing <React.StrictMode> fixed it for me.

Renaldorenard answered 17/10, 2022 at 16:49 Comment(0)
C
7

I ran into the same issue however the following steps helps me

Step 1:

draggableId should be string, not an integer 

as per https://github.com/atlassian/react-beautiful-dnd/issues/1512

Step 2:

if you are coming from EggHead tutorial, this might have missed. Try to add a key property as mentioned in the top answer

<Draggable key={item.id} draggableId={item.id.toString()} index={index} >
Codpiece answered 11/8, 2021 at 1:4 Comment(0)
E
6

If you are looking for a solution

  • Without removing Strict Mode
  • Without replacing the whole react-beautiful-dnd library

1. Create this StrictModeDroppable component in your project:

import { useEffect, useState } from "react";
import { Droppable, DroppableProps } from "react-beautiful-dnd";

export const StrictModeDroppable = ({ children, ...props }: DroppableProps) => {
  const [enabled, setEnabled] = useState(false);

  useEffect(() => {
    const animation = requestAnimationFrame(() => setEnabled(true));

    return () => {
      cancelAnimationFrame(animation);
      setEnabled(false);
    };
  }, []);

  if (!enabled) {
    return null;
  }

  return <Droppable {...props}>{children}</Droppable>;
};

2. Then replace <Droppable> components in your project with <StrictModeDroppable>.

It should work!


Source: https://github.com/atlassian/react-beautiful-dnd/issues/2399#issuecomment-1175638194

Engleman answered 6/11, 2023 at 11:4 Comment(1)
This should be the top answer here.Ariella
J
5

If you still getting this issue, there was a simple solution for you. Just remove <React.StrictMode> from the index.js.

Jehias answered 9/3, 2023 at 15:23 Comment(0)
S
2

It's a simple fix. The other answers are making it too complicated.

Error: Unable to find draggable with id: X

The error is simply saying that Droppable is unable to find the draggable component with the given ID. That's because the same ID and key are being provided to the draggable component.

To fix this issue, just make sure ID and DraggableId are different in the Draggable component. That's the main issue which causes this error.

<Draggable draggableId={id} index={index} key={id + '-button'}>

Note: Dragging doesn't work if <React.Strictmode> is present at top level, it should be removed.

Secretarial answered 6/6 at 6:4 Comment(0)
N
1

Try converting the integer value to a string. It'll solve the issue as it solved mine

{tasks.map((t, index) => (
  <Draggable
    draggableId={t._id.toString()}
    index={index}
    key={t._id} >
     ....
  </Draggable>
}
Nickens answered 29/12, 2021 at 14:37 Comment(0)
S
1
  1. There is a YouTube lesson on react-beautiful-dnd. He posted his lesson progress in the Code Sandbox enter link description here You can open it and make sure. But I have on "react": "^18.1.0" does not work and gives an error

    Unable to find draggable with id:X

    And on older versions of react everything also works without errors.Try for example another version of react"^17.0.2"ю It worked for me

  2. Also remember, when installing the react-beautiful-dnd library, were there any dependency conflicts? Maybe you have not established all the connections and because of this it does not work correctly. In any case, as a test, I suggest downloading the code from the lesson and checking in my project whether it works or not. If it works, it means an error in the code, if not, then react-beautiful-dvd does not work correctly

Spotlight answered 28/4, 2022 at 11:27 Comment(0)
L
1

I hope this will help someone. If you are experiencing this even your code is correct. Please check your react version. In react version 18.0, dnd will show unable to find draggable with id warning. Current solution to downgrade to 17 and it works flawlessly. I searched for the solution like remove strict mode, using dynamic import and other things but currently it's related to react 18.

Lindsylindy answered 21/6, 2022 at 11:3 Comment(0)
D
1

It works with react-beautiful-dnd and React 18 in StrictMode. https://github.com/atlassian/react-beautiful-dnd/issues/2399#issuecomment-1175638194

Djakarta answered 12/1, 2023 at 17:13 Comment(0)
A
1

To mirror @MarcinHubert's comment in one of the answers, Atlassian no longer maintains this repo, and there is a drop-in replacement that is being actively maintained that fixes this problem: https://github.com/hello-pangea/dnd

Apollus answered 12/12, 2023 at 22:22 Comment(1)
In my case, even using this lib, the error was present, but it was my fault. I basically forgot to add key attribute to the Droppable, only the Draggable had the key, now both have, and everything works fine.Doering
C
0

Post it here, since this is the top link the Google for the same error.

It might be the case, that you do not render an element with the provided.dragHandleProps

<div>
      {someCondition && (
           <div>
               <DragIndicatorIcon {...provided.dragHandleProps}/>
           </div>
      )}
</div>

In this case move {...provided.dragHandleProps} outside the condition

<div {...provided.dragHandleProps}>
      {someCondition && (
           <div>
               <DragIndicatorIcon {...provided.dragHandleProps}/>
           </div>
      )}
</div>

Found this solution here

Cultism answered 29/9, 2021 at 13:17 Comment(0)
K
0

Resolved this issue by converting draggableId into string

Keeter answered 28/9, 2022 at 12:3 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Yucca
M
0

For those who are experiencing the same problem with the @hello-pangea/dnd library, converting the id to string worked for me.

<Draggable key={ticket.id} draggableId={ticket.id.toString()} index={index}>
Montevideo answered 29/3, 2023 at 17:36 Comment(0)
L
0

Make sure you have provided - draggableId, key and ref

Leis answered 12/4, 2023 at 6:17 Comment(0)
F
0

I actually faced the same issue but the above solution worked for me. I was using Next.js 14 and typescript:

"use client";

import { useEffect, useState } from "react";
import { Droppable, DroppableProps } from "react-beautiful-dnd";

export const StrictModeDroppable = ({ children, ...props }: DroppableProps) => {
  const [enabled, setEnabled] = useState(false);

  useEffect(() => {
    const animation = requestAnimationFrame(() => setEnabled(true));

    return () => {
      cancelAnimationFrame(animation);
      setEnabled(false);
    };
  }, []);

  if (!enabled) {
    return null;
  }

  return <Droppable {...props}>{children}</Droppable>;
};



<DragDropContext onDragEnd={handleDragEnd}>
      <StrictModeDroppable droppableId="items">
        {(provided) => (
          <div ref={provided.innerRef} {...provided.droppableProps}>
            {stateItems.map((item, index) => (
              <ListItem key={index} id={index.toString()} index={index}>
                {item}
              </ListItem>
            ))}
            {provided.placeholder}
          </div>
        )}
      </StrictModeDroppable>
    </DragDropContext>
Finegan answered 17/1 at 13:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.