Open ghost opened 4 years ago
I implemented a nested RBD that works great. I have 3 layers, and can drag across each layer quite well. However, my outermost layer is quite large and therefore I implemented react-window (virtualization) onto it. It seems to work quite well, except a nested layer when dragging seems to be offset by several hundred pixels (e.g. 500 px to the left and down) from where the cursor actually is. Any ideas?
edit: using the renderClone
api for each of the nested Droppables actually fixes it. The console complains that there's no placeholder
, but it seems to work and the API docs say you can use renderClone even without the [nested] lists being virtualized. 👌
edit2: for any future intrepidors (is that a word?), I was able to maintain my memoization on the components by adding a dontMemoize
prop to the renderClone and checking the transform
on the provided.draggableProps
such as:
export default React.memo(Picture, (prevProps, nextProps) => {
if (prevProps.dontMemoize || nextProps.dontMemoize) return false;
return (
prevProps.provided.draggableProps.style.transform ===
nextProps.provided.draggableProps.style.transform &&
prevProps.id === nextProps.id // or whatever memoization check you have
);
});
Interesting. So you don't and can't virtualize the whole nested RBD but can virtualize a single nesting layer. Well, better than no virtualization.
Any possibility of you throwing the essence of your solution into a code sandbox? Thanks.
This is basically the same thing: https://codesandbox.io/s/simple-virtual-list-board-vgvzt
The only difference is the virtualization is on the inside layer. If you move it up to the top layer, just replace the {provided.placeholder}
api with a renderClone
(now being used in both layers) and you should be good to go. For any further nesting, just keep using renderClone
over placeholder. Let me know if that makes sense.
@switz
I tried doing what you mentioned, but I'm running into a bit of an error trying to move items from one list to another.
https://codesandbox.io/s/wip-outerlist-uses-window-scroller-5hcbn?file=/src/index.js
Used the codesandbox link you posted above as a starting point, and tried to make changes until I could get something working.
I added helper functions that did the virtualization for columns just like it was doing for items.
"Base JSX" : Item -> Col
"Draggable Box" : Row -> Column
"Renderer" : makeRowRenderer -> makeColumnRenderer
"DropVirtList" : ItemList -> ColList
But when I try to drag one item to another list and scroll down with it, it gives an error: Invariant failed: Cannot find droppable entry with id [column-4]
Are you able to tell what's going wrong?
I'm not sure exactly what's happening but if you log out the column.id
in ItemList, I'm seeing it get reset to the root columns for some reason on occasion:
Even though it should be the columns in the view. I'd play around with it and figure out why that's happening, clearly the ListItem Droppables are not being rendered properly, perhaps has to do with your memo functions (which don't seem to have any special checks, like checking if column.id
has changed).
CONTEXT
I have a tree data structure that, if I flatten the tree into a linear list, can use RBD with react-window virtualization for a very performant drag and drop where all nodes are equal.
But desiring to support drag and drop for a hierarchy of a node and all its children in a single drag, I implemented a nested RBD solution for the tree similar to your example code: https://react-beautiful-dnd.netlify.com/?path=/story/complex-vertical-list--nested-vertical-lists. It works well but is sluggish with large lists. As per your example, this nested solution does not use react-window.
QUESTION
Is it possible to have a nested RBD solution with react-window virtualization? Or are they inherently incompatible, the one requiring nesting and the other requiring a flat linear list?
Thank you.