Open giovannipds opened 2 years ago
Has there been any update on this issue?
also got this issue, mine fine in firefox, but fail in chrome
Edit: I found the solution. In onDragOver, any state update you make, wrap it inside startTransition
or requestAnimationFrame
. startTransition
is native way by react though
So, here's my demo. In my case, it's happening because of mixed height items. When all items are of equal height, there's no error.
[
https://github.com/clauderic/dnd-kit/assets/13780952/3dd5e5b3-901f-4344-9928-9c35cc9c114d
](url)
same issue +1
I had the same problem and I fixed it by using a composition of existing collision-detection algorithms:
import { closestCorners, closestCenter, pointerWithin } from "@dnd-kit/core";
export function customCollisionDetectionAlgorithm(args) {
const closestCornersCollisions = closestCorners(args);
const closestCenterCollisions = closestCenter(args);
const pointerWithinCollisions = pointerWithin(args);
if (
closestCornersCollisions.length > 0 &&
closestCenterCollisions.length > 0 &&
pointerWithinCollisions.length > 0
) {
return pointerWithinCollisions;
}
return null;
}
And then of course used it in the DndContext
:
<DndContext
onDragStart={onDragStart}
onDragEnd={onDragEnd}
onDragOver={onDragOver}
sensors={sensors}
collisionDetection={customCollisionDetectionAlgorithm}
>
I am getting the same issue, I have tried the suggestions above but no joy.
Here is my code:
const SortableList = ({ items, onSortEnd, hasDragHandle }: SortableListProps) => {
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
const getIndex = (id: UniqueIdentifier) => items.indexOf(+id);
const sensors = useSensors(
useSensor(MouseSensor, {
// Require the mouse to move by 10 pixels before activating.
// Slight distance prevents sortable logic messing with
// interactive elements in the handler toolbar component.
activationConstraint: {
distance: 10,
},
}),
useSensor(TouchSensor, {
// Press delay of 250ms, with tolerance of 5px of movement.
activationConstraint: {
delay: 250,
tolerance: 5,
},
}),
);
const previewItems = useMemo(
() => items.map((item) => previewedResultsGrid[item.index]),
[items],
);
return (
<DndContext
sensors={sensors}
autoScroll={false}
onDragStart={({ active }) => {
if (active) {
setActiveId(active.id);
}
}}
onDragEnd={({ active, over }) => {
if (over && active.id !== over.id) {
onSortEnd({
oldIndex: getIndex(active.id),
newIndex: getIndex(over.id),
});
}
setActiveId(null);
}}
onDragCancel={() => setActiveId(null)}
>
<SortableContext items={previewItems} strategy={rectSwappingStrategy}>
<div
ref={parentRef}
className={cx(
stl`relative select-none overflow-x-hidden overflow-y-scroll`,
'NewRuleResult_container',
currentRule.hasConditions && currentRule.hasConsequences && 'with-confirmBar',
)}
style={{
...containerStyle,
width: layout.width,
height: layout.height,
paddingBottom: currentRule.hasConditions && currentRule.hasConsequences ? 85 : 0,
}}
>
<ul
className={stl`relative overflow-hidden`}
style={{
height: totalSize + DETAILS_EXPANSION_HEIGHT,
width: layout.width - containerLeftPadding - containerRightPadding,
}}
>
{virtualItems.map((item) => {
const columnWidth = layout.itemWidth + layout.gutterSize;
const sharedItemStyles: CSSProperties = {
position: 'absolute',
top: item.start,
height: rowHeight,
...(layout.mode === 'grid'
? {
width: columnWidth,
paddingTop: MULTISELECT_CHECKBOX_SIZE / 2,
}
: { width: layout.itemWidth, padding: MULTISELECT_CHECKBOX_SIZE / 2 }),
};
return (
<Fragment key={`${layout.mode}-${item.index}`}>
{previewedResultsGrid[item.index].map((result, columnIndex) => {
return (
<li
key={result.objectID}
style={{ ...sharedItemStyles, left: columnWidth * columnIndex }}
>
hello
</li>
);
})}
;
</Fragment>
);
})}
;
</ul>
</div>
</SortableContext>
</DndContext>
);
};
return <SortableList items={virtualItems} onSortEnd={onSortEnd} hasDragHandle={true} />;
};
export const SortableResultsItems = SortableContainer(observer(ResultsItems));
@thomasbritton Try following:
...
onDragStart={({ active }) => {
if (active) {
setTimeout(() => setActiveId(active.id), 0)
}
}}
...
the solution by @HenrikZabel works. However, I implemented it in OnDragOver to update the array at a timeout of 5 ms. the issue is clearly happening with ondragover.
I had the same issue although I did not use onDragOver.
For me the problem was that i used the PointerSensor
instead of the MouseSensor
const sensors = useSensors(useSensor(MouseSensor)); <----- This fixed it
<DndContext sensors={sensors} onDragEnd={handleDragEnd} collisionDetection={closestCenter}>
<SortableContext items={items} strategy={rectSwappingStrategy}>
{...children}
</SortableContext>
</DndContext>
So changing the Sensor fixed it for me.
Maybe this helps someone having the same issue.
I had the same problem and I fixed it by using a composition of existing collision-detection algorithms:
import { closestCorners, closestCenter, pointerWithin } from "@dnd-kit/core"; export function customCollisionDetectionAlgorithm(args) { const closestCornersCollisions = closestCorners(args); const closestCenterCollisions = closestCenter(args); const pointerWithinCollisions = pointerWithin(args); if ( closestCornersCollisions.length > 0 && closestCenterCollisions.length > 0 && pointerWithinCollisions.length > 0 ) { return pointerWithinCollisions; } return null; }
And then of course used it in the
DndContext
:<DndContext onDragStart={onDragStart} onDragEnd={onDragEnd} onDragOver={onDragOver} sensors={sensors} collisionDetection={customCollisionDetectionAlgorithm} >
This also seems to fix the same issue I was facing. Thank you.
So I thought the custom collision detection was fixing it, but it turns out it was not. I instead implemented a 0ms debounced state setter based on this comment and this is now working perfectly.
import {
DndContext,
DragOverlay,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
type DragEndEvent,
type DragOverEvent,
type DragStartEvent
} from "@dnd-kit/core";
import { useDebouncedCallback } from "use-debounce";
// ...
export function Kanban() {
// ...
const [items, setItemsUndebounced] = useState<Item[]>(initialItems);
const setItems = useDebouncedCallback(setItemsUndebounced, 0);
// ...
function onDragOver(event: DragOverEvent) {
// ...
setItems((items) => {
// ...
return arrayMove(items, activeIndex, overIndex);
});
// ...
}
// ...
}
Edit: I found the solution. In onDragOver, any state update you make, wrap it inside
startTransition
orrequestAnimationFrame
.startTransition
is native way by react thoughSo, here's my demo. In my case, it's happening because of mixed height items. When all items are of equal height, there's no error.
[
Screen.Recording.2023-12-07.at.3.25.11.PM.mov ](url)
thank you so much your solution helped me
I had the same error, i was using the Component with useDroppable() hook within the same component that uses it, i just separated the component with useDroppable() hook into a separate file and imported into the main component. Now it works! Hope it would help someone.
Wrapping the state update call in a debounce helps solve this issue as well
for anyone meet this problem, I am rendering the sortableItem in a hook, maybe you should useMemo the node to avoid infinite rendering
function useParser() {return {TreeNode}}
the TreeNode is wrapped in a useMemo and the code is no error
I'm just reopening this issue https://github.com/clauderic/dnd-kit/issues/496, people has been posting there, so prolly the issue is still around (I have that in the project that I'm working on it too lol).