React Beautiful DND - Ошибка "Невозможно найти перетаскиваемый элемент с id: 1"
Вопрос на StackOverflow: Ошибка "Unable to find draggable with id: X" при многократном перетаскивании в React
В приведенном ниже коде интерфейс отображает два компонента "Column", и каждая колонка содержит два перетаскиваемых элемента, называемых "Tasks". Когда пользователь перетаскивает "Task" между колонками, код работает, но не всегда. При непрерывном перетаскивании элементов в какой-то момент перетаскивание останавливается, и пользователь получает ошибку:
Unable to find draggable with id: X
Я не понимаю, почему это происходит и как это исправить.
Примечание: Я предполагаю, что библиотека требует, чтобы при перетаскивании элементов вы перерасставляли и обновляли своё состояние в функции onDragEnd
.
Вот мой код:
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];
let sourceGroupIndex = taskData.findIndex(val => val.groupName === source.droppableId);
let draggedTask = taskData[sourceGroupIndex].tasks[source.index];
let sourceListCopyWithElementRemoved = taskData[sourceGroupIndex].tasks.filter((_, index) => index !== source.index);
let destinationGroupIndex = taskData.findIndex(val => val.groupName === destination.droppableId);
taskData[destinationGroupIndex].tasks.splice(destination.index, 0, draggedTask);
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 { droppableId, list, type } = props;
let style = {
backgroundColor: "orange",
height: "300px",
width: "400px",
margin: "100px"
};
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 { 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;
Можно ли узнать, что вызывает эту проблему и как её решить?
5 ответ(ов)
Если вы получаете следующую ошибку в React 18:
Unable to find draggable with id:
Попробуйте удалить StrictMode
из вашего кода.
В некоторых случаях использование StrictMode
может вызывать проблемы с библиотеками, которые не полностью поддерживают его или работают некорректно в этом режиме. Убедитесь, что вы протестировали ваше приложение после отключения StrictMode
, чтобы подтвердить, что это решает проблему. Однако не забывайте, что StrictMode
предназначен для выявления потенциальных проблем и улучшения качества кода, поэтому стоит также рассмотреть возможность обновления используемых библиотек для обеспечения совместимости с StrictMode
.
В данном случае не для этого, но для всех - проверьте provided.draggableProps
, а не 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>
React Beautiful DnD (RBD) пытается найти узел по provided.draggableProps
. Если эти свойства отсутствуют, вы получите ошибку: Unable to find draggable with id: X
. Убедитесь, что вы правильно используете provided.draggableProps
для обработки перетаскивания.
У меня была похожая проблема, когда я перебирал несколько перетаскиваемых элементов и забыл указать свойство key
. Добавление key
к компоненту Draggable
помогло решить проблему:
{tasks.map((t, index) => (
<Draggable
draggableId={t._id}
index={index}
key={t._id} >
....
</Draggable>
))}
Не забывайте указывать уникальный key
для каждого элемента в списке, чтобы React мог корректно управлять изменениями и оптимизировать рендеринг!
Библиотека больше не поддерживается. Я перешел на форк:
https://github.com/hello-pangea/dnd
И все проблемы были решены.
Если вы ищете решение, которое:
- Не требует отключения Strict Mode
- Не замены всей библиотеки
react-beautiful-dnd
1. Создайте компонент StrictModeDroppable
в вашем проекте:
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. Затем замените компоненты <Droppable>
в вашем проекте на <StrictModeDroppable>
.
Это должно сработать!
Источник: GitHub Issue
Как реализовать дебаунс?
Обнаружена ошибка: Невозможное нарушение: Неверный тип элемента: ожидался строковый тип (для встроенных компонентов) или класс/функция, но получен объект
Добавление тега script в React/JSX
"Не используйте Route или withRouter() вне Router при работе с react-router 4 и styled-components в React"
React + Redux — Замедление работы onChange в Input при вводе, когда значение берется из состояния