-
-
Notifications
You must be signed in to change notification settings - Fork 664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Asynchronous reordering and drop animation #833
Comments
Ok, it would appear I was hasty in my assumption that the async aspect was to blame - I found a way to refactor so that enough data was stored in the dragged item |
I have the same issue. I'm using To make it work currently, I'm storing a copy of the state locally in a variable with |
It seems to act better if I use But overall I'd say try to use |
Happy to say the revised approach works pretty well! It seems to smooth over a lot of issues I was having at once. 2022-07-13.21-27-11.mp4When I drag outside of a category I reset the item's data to its snapshotted original state, and it animates back to its original position, even if it was moved into an entirely different category while it was dragged (because changing data in Doing that was relatively easy, I just store |
Do you have the code for your solution? I'm the same issues :( |
My app interactions have changed a lot since I wrote that reply, but it would be something like this (using very simple pseudo code for updating the item state, stored in let originalCategory = null;
function DragDemo() {
return (
<Draggable
onDragStart={({ active }) => {
// store this at the start of the gesture so you can reset it if the drag is cancelled
originalCategory = active.data.current.category;
}}
onDragOver={({ over, active }) => {
// immediately move items during the drag to whatever place they are over
active.data.current.category = over.data.current.id;
}}
onDragEnd={({ over, active }) => {
if (!over) {
// the drag ended in white space; reset to the original category
active.data.current.category = originalCategory;
}
}}
onDragCancel={({ active }) => {
if (active) {
// same thing
active.data.current.category = originalCategory;
}
}}
/>
);
} In plain language: store the original state when the drag starts, update item state in realtime during the drag using The reason I ended up switching away from this is I added Undo to my app, which meant that making these "temporary" immediate changes was no longer a good experience. However, I had also upgraded my custom IndexedDB framework to include instant in-memory changes, so the async problem was no longer a limiting factor anymore. |
It seems dnd-kit works fine with local state but not so much with async state. A solution would be for dnd-kit to wait for And then users could write: function Component() {
const items = useMyRemoteItems();
async function onDragEnd({ over, active }) {
await updateMyRemoveItems(over, active);
}
return (
<DndContext items={items} onDragEnd={onDragEnd}>
{/* ... */}
</DndContext>
);
} No need for That would be particularly useful with react-query (#921) and optimistic UI. |
I'm building a sortable list, but the logic for reordering items is more complex than an array move and involves querying a local database to determine the appropriate sort key to apply to the dropped item. I can explain the constraints a bit more if needed, but suffice to say there's some logic to
await
before I actually modify the state of the list.This works fine in theory (the operation is so fast that the item appears to reorder instantly), but the issue I've run into is that the drop animation for DragOverlay measures the destination position ASAP, and so it catches the 1 or 2 frames before my reorder is applied, and the item animates back to its original position before jumping to its final one.
2022-07-13.19-54-00.mp4
I realize this is a pretty obtuse constraint, but it would be a lot of work to introduce an immediate cached layer over my data to "optimistically" move the item before writing to storage. Before I commit to that I wanted to see if there were any options or deeper configuration I could leverage to fix the issue.
I think ultimately what would help is if I could manually trigger the drop animation as part of my reordering logic. Something like
such that the drop animation wouldn't measure the destination transform until it was unpaused.
For now I've just disabled the drop animation, the difference is fairly subtle in most cases anyway.
The text was updated successfully, but these errors were encountered: