React-beautiful-dnd: > Invariant failed: Draggable[id: 8]: Unable to find drag handle

Created on 20 Feb 2020  路  18Comments  路  Source: atlassian/react-beautiful-dnd

Please head to the @atlaskit/tree issue tracker.

We do not track @atlaskit/tree issues in the react-beautiful-dnd project

more information required wontfix 鈽狅笍

Most helpful comment

@rxannelow If you use SSR i try to use

import { resetServerContext } from "react-beautiful-dnd"




resetServerContext()

and it work!!! :)

All 18 comments

Screen Shot 2020-02-20 at 10 33 13

I have followed your video tutorials closely, ensured that draggableId is a string and mapped items get a key. I'm still unable to get dnd to function on page load. However, after making changes to my code and app auto saves, the dnd works as I intended.

Hi there!

Thanks for raising this issue. Can you please create a standalone example on codesandbox.io using our boilerplate: https://codesandbox.io/s/k260nyxq9v

Without a standalone example, we will not be able to action this one

Cheers!

Hi Alex,

Thank you for getting back to me. I tried replicating my code in your boilerplate and it works just fine. So I don't know how else to show you an example of the problem.

But, one thing I noticed when inspecting the draggable object is the data-rbd-draggable-context-id doesn't start from 0 and every time I refresh the page, the value increases.

Might you have an idea what could be causing the problem?

@rxannelow If you use SSR i try to use

import { resetServerContext } from "react-beautiful-dnd"




resetServerContext()

and it work!!! :)

+1 here

<DragDropContext onDragEnd={ this.onDragEnd.bind(this) }>
      <Droppable droppableId="images" >
        {
          (provided) => (
            <div ref={provided.innerRef } {...provided.droppableProps} >
            {this.state.images.map( this.image.bind(this) )}
            </div>
          )
        }
      </Droppable>
</DragDropContext>
<Draggable key={ el.id } draggableId={ el.id } index={ idx }>
      {
        ( provided, snapshot ) => {
          return <Box  overflow="hidden" rounded="md" borderWidth="1px" cursor="pointer" {...provided.draggableProps} {...provided.draggableProps} ref={provided.innerRef}>
                <Image src={ data.image } alt={ idx } objectFit="cover" height="175px" width="100%" />
          </Box>
        }
      }
</Draggable>

Screen Shot 2020-04-23 at 11 16 32 AM

@samullman you use twice draggableProps and so dragHandleProps are missing

{...provided.draggableProps} {...provided.draggableProps} =>
{...provided.draggableProps} {...provided.dragHandleProps}

same issue here @alexreardon

@samullman Spread rest props to the top element of the Box component.

Example

import * as React from "react";

function Box(props) {
  const { overflow, rounded, borderWidth, cursor, ...rest } = props;
  // ... some code

  return <div {...rest}>....</div>
}

rest props is provided.draggableProps and provided.dragHandleProps.

this issue reason is not found dragable props element.

@mina4gerges

@rxannelow check my comment.

Having this same issue in a Chrome Extension environment. Have it working identically in a Sandbox, but getting same error posted by @samullman above, except I do have the correct props spread on each.

All the items are rendering, but no action when trying to drag anything.

Any reason it may not work in a Chrome Extension? Have inspected the elements and when compared to the demo project they have all the same props on both the Droppable and Draggable elements.

I'm facing the same issue but testing with enzyme.
image

This are my components:
_(I removed some props to only show the ones that belongs to the library)_

<DragDropContext onDragEnd={this.onDragEndHandle}>
  <Droppable droppableId="1-dpb">
    {(provided) => (
      <CustomizedTemplate  provided={provided}  />
    )}
  </Droppable>
</DragDropContext>
import React from 'react';
// Components
import BannerExpand from '../../../organism/BannerExpand';

const Customized = ({ provided }) => (
  <div ref={provided.innerRef} {...provided.droppableProps} >
    {campaigns.map((campaign, index) => (
      <BannerExpand
        position={campaign.id}
        index={index}
      />
    ))}
    {provided.placeholder}
  </div>
);

export default Customized;
/* eslint-disable react/jsx-one-expression-per-line */
import React from 'react';
import { Draggable } from 'react-beautiful-dnd';

const BannerExpand = ({position, index}) => (
    <Draggable draggableId={`${position}-dbl`} index={index}>
      {(provided) => (
        <div
          {...provided.draggableProps}
          {...provided.dragHandleProps}
          ref={provided.innerRef}
        >
          Drag me !
        </div>

    </Draggable>
  );
};

export default BannerExpand;

I debug the component with debug() and i got this:
image

I get the message from above if I'm using with enzyme with act for async events inside the useEffect hook or the componentDidMount function:

let wrapper = null;

await act(async () => {
  wrapper = mount(<Component />);
});

If i change the code to a sync version, it works ok but I'm still getting the errors from the first image:

let wrapper = mount(<Component />);

I have the same issue using FlexLayout after opening a new window it throws those errors

index.js:1 react-beautiful-dndA setup problem was encountered.> Invariant failed: Draggable[id: item-1]: Unable to find drag handle

and here is my code

import React, { useEffect, useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

export default function App() {

  // a little function to help us with reordering the result
  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  // const grid = 8;

  const getItemStyle = (isDragging, draggableStyle) => ({
    // some basic styles to make the items look a bit nicer
    userSelect: 'none',
    padding: 10,
    margin: `0 0 8px 0`,

    // change background colour if dragging
    background: isDragging ? 'lightgreen' : 'grey',

    // styles we need to apply on draggables
    ...draggableStyle,
  });

  const getListStyle = (isDraggingOver) => ({
    background: isDraggingOver ? 'lightblue' : 'lightgrey',
    padding: 8,
    width: 250,
  });
  const [stateItems, setStateItems] = useState([
    {
      id: `item-1`,
      content: `item $1`,
    },
    {
      id: `item-2`,
      content: `item $2`,
    },
    {
      id: `item-3`,
      content: `item $3`,
    },
    {
      id: `item-4`,
      content: `item $4`,
    },
  ]);


  const onDragEnd = (result) => {
    // dropped outside the list
    if (!result.destination) {
      return;
    }
    const items = reorder(
      stateItems,
      result.source.index,
      result.destination.index
    );
    setStateItems(items);
  };

  // Normally you would want to split things out into separate components.
  // But in this example everything is just done in one place for simplicity
  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="droppable">
        {(provided, snapshot) => (
          <div
            {...provided.droppableProps}
            {...provided.dragHandleProps}
            ref={provided.innerRef}
            style={getListStyle(snapshot.isDraggingOver)}
          >
            {stateItems.map((item, index) => (
              <Draggable key={item.id} draggableId={item.id} index={index}>
                {(provided, snapshot) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    style={getItemStyle(
                      snapshot.isDragging,
                      provided.draggableProps.style
                    )}
                  >
                    {item.content}
                  </div>
                )}
              </Draggable>
            ))}
            {provided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
  );
}


I created a sandbox link to demonstrate my problem pleas check

https://toqkl.csb.app/

I have another example using react-new-window it is not working check codesandbox link
https://q5mf6.csb.app/

I have this issue but I'll attempt to debug it, the same code works fine in the storybook for the project when I copy paste it. So seems it might be happening when fired at a certain lifecycle point.

It appears this happens when the component this is contained within takes a while to mount the items even if they are mounted later.

The draggable component runs and tries to read the ref for the DOM which hasn't been created yet.

Solved

  • Note : I used NextJS for React
    I was getting the same error in development and production as well.

It occurs because DOM and window is not loaded before that our component gets loaded.

Here's a solution :

  • Make Sure your window object is ready before your component loads up.
  • Here's code that I have implemented

import React, {useEffect, useState} from "react"; import dynamic from "next/dynamic"; const Column = dynamic(import("./Column/Column")); function ScrumBoard() { const [winReady, setwinReady] = useState(false); useEffect(() => { setwinReady(true); }, []); return ( <div className="pl-4 pr-4 pt-3"> ` <h5>Frontend Board</h5>` {winReady ? <Column /> : null} </div> ); } export default ScrumBoard;

Was this page helpful?
0 / 5 - 0 ratings

Related issues

OmriAharon picture OmriAharon  路  3Comments

heymartinadams picture heymartinadams  路  3Comments

joshmillgate picture joshmillgate  路  3Comments

vrg-success picture vrg-success  路  3Comments

alexreardon picture alexreardon  路  3Comments