react-beautiful-dnd: destination is equal to null
Here is the thing. I'm learning to React beautiful dnd in by building a todo app. And I have set up the app as far as styling the component and writing the logic to display the todo cards.
The problem is this, as I drag the card in todo to progress or done, the property "destination", in an object logged in the console (check the code to see where it's logged) destination is equal to null. It's supposed to be equal to an object. What seems to be the problem.
The full code is located in the link below:
https://codesandbox.io/s/async-fast-hziot?file=/src/App.js
Preview:
import "./styles.css";
import { useState } from "react";
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
export default function App() {
const [populateStore, setPopulateStore] = useState(
{
todo: {
_id:"todo",
data: [
{
_id: 'ms7690fvs6sd53h328sof-0sdf',
author: 'anonymous',
title: 'Going to the pack',
date: '11th, January 2022'
},
{
_id: 'sdfdf32gf98tddswjk73i2r',
author: 'anonymous',
title: 'Visit my parents for the holiday',
date: '11th, January 2022'
}
]},
inprogress: {
_id: "in progress",
data:[]},
done: {
_id:"done",
data: []
}
}
);
function handleOnDragEnd(result) {
console.log(result, "result")
}
return (
<div className="populate-container">
{Object.entries(populateStore).map(([title, array],index) => {
return (
<div className="todo-container" key={index}>
<div className="todo-headings">
{title}
</div>
<DragDropContext onDragEnd={handleOnDragEnd}>
<Droppable
droppableId={`${array._id}`}
type={`${array._id}`}
>
{
(provided) => {
return (
<div className="_droppable" {...provided.droppableProps} ref={provided.innerRef}>
{
array.data.map((item, id) => {
return (
<Draggable key={id} draggableId={`${id}`} index={id}>
{
(provided) => {
return (
<div className="card" ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} key={id}>
<div className="card-description">
<h5>{item.title}</h5>
<p>
{
item.date
}
</p>
</div>
</div>
)
}
}
</Draggable>
)
})
}
{provided.placeholder}
</div>
)
}
}
</Droppable>
</DragDropContext>
</div>
)
})}
</div>
);
}
Solution 1:
The problem was two things.
- The tag "DragDropContext" was meant to be the first tag before mapping out the stored data in the state "populate hook". But instead, I was mapping out the data first with DragDropContext being a child node.
This is the right way:
<DragDropContext onDragEnd={handleOnDragEnd}>
{Object.entries(populateStore).map(([title, array],index) => { ......
Not this:
{Object.entries(populateStore).map(([title, array],index) => { ......
<DragDropContext onDragEnd={handleOnDragEnd}>
- Then the second was an unseen problem not asked initially at the question section and that is the id of the Droppaple and the draggable. Always make sure the ids of these tags are in strings, not numbers, and make sure the ids are not alike for example the problem in my code, the id of the draggable card in the "todo", "progress" and "done" columns were both the number 1 (I manually added an object to the "done" array located in the state to test it, and I was using the index in the higher-order function, "map" as an id in the draggable tag), so whenever I try to pick up the first one, in the "todo" column I will end up carrying the first one in the "done" column. So I resolved that by using the string id in the object.
I used this:
id: _id: "ms7690fvs6sd53h328sof-0sdf" in <Draggable key={id}
Not this anymore:
array.data.map((item, id) => { in <Draggable key={id}
when id = 1 or 2 or 3 and so on.
You can view the solution in the javascript file "answer_code.js" in the link provided in the question section.