We are planning on shipping virtual list support #68. However, I am not sure what the api should look like.
👨🏫 Full disclosure: I am not a virtual list expert, so please feel free to correct any inaccuracies in my understanding
One big difference from an API perspective of supporting virtual lists is that the dragging item (<Draggable />) can be removed during a drag. Currently, this is not the case. So in order to support virtual lists we need to support the ability to render a clone as the dragging item.
import React from "react";
import ReactDOM from "react-dom";
import { FixedSizeList as List } from "react-window";
import { Draggable, VirtualDroppable } from "react-beautiful-dnd";
// Note: this example won't work - it is just to see what an api could look like
const Row = ({ index, style }) => (
<Draggable draggableId={index}>
{provided => (
<div
{...provided.dragHandleProps}
{...provided.draggableProps}
style={{
...style,
...provided.draggableProps.style
}}
ref={provided.innerRef}
>
Row {index}
</div>
)}
</Draggable>
);
const Example = () => (
<VirtualDroppable
droppableId="droppable"
renderDraggingItem={provided => (
<div
{...provided.dragHandleProps}
{...provided.draggableProps}
ref={provided.innerRef}
>
Drag Me
</div>
)}
>
{droppableProvided => (
<List
height={150}
itemCount={1000}
itemSize={35}
width={300}
innerRef={droppableProvided.innerRef}
>
{Row}
{/* no placeholder needed */}
</List>
)}
</VirtualDroppable>
);
const rootElement = document.getElementById("root");
ReactDOM.render(<Example />, rootElement);
Droppable renders a clone?Right now I am thinking of having a renderDraggingItem prop on the Droppable (or VirtualDroppable) which would be responsible for rendering the clone.
Then I think, should we always render the dragging item as a clone? I think not as things are working quite well right now, but it is something to consider.
We could get away from needing a clone if we could mark an item in a virtual list as persistent after a drag starts so the react component is never unmounted.
Droppable placeholderThis would not be needed for a home list as the full list size would not collapse when an item is removed. A foreign list might need an insertion to make room... Oh dear
Edge case - virtual table. A "row" is a <tr><td>..</td></tr> and has to be rendered inside a _parent_ table which could be create by a VirtualTable itself.
So in short - some times you have to render a clone inside a virtual List, and some Lists gives you the ability to "inject" something inside, that changes how renderDraggingItem works - it shall be just passed down to render props.
<VirtualDroppable
droppableId="droppable"
renderDraggingItem={provided => (
<div
{...provided.dragHandleProps}
{...provided.draggableProps}
ref={provided.innerRef}
>
Drag Me
</div>
)}
>
{({droppableProvided, VirtalDraggingItem} => (
<List
height={150}
itemCount={1000}
itemSize={35}
width={300}
innerRef={droppableProvided.innerRef}
extraChildren={VirtalDraggingItem} // not a real API
>
{Row}
</List>
)}
</VirtualDroppable>
);
That would be more or less any VirtualList library compatible, as long as removes _decision_ from DND side.
There is also another approach - _replicate item_.
ref to the item nodegetComputedStyles' andgetClientBoundaryRect+position:absolute`This is a relatively fast operation, but it would not so easy to mirror all possible changes in runtime to the clone, potentially "freezing" it. Which could be not a bad thing.
rbd could clone the item itself...
The main issue is letting the consumer control and use the snapshot.. 🤔
Right now a sensor is responsible for initiating a drag and movements during a drag. If we move to a clone strategy (which I think we will have to), then the sensor would only be responsible for starting a drag. Something else would need to manage the event listeners for a drag
I believe you should always render a clone in a virtual list, it would save you from a couple of headaches related to items disappearing. And the user should also be able to use the snapshot, to be able add a class or some other special thing to the item that is being dragged. What do you mean by control?
The lifecyle of the snapshot and other things gets a bit complicated when moving to a clone
I am playing with this. It looks like there will be a lot of heavy lifting

Whiteboarding the event listener problem with @kangweichan

// new export: VirtualDroppable
<VirtualDroppable
droppableId="droppable"
draggingItemClone={(provided: DraggableProvided, snapshot: DraggableStateSnapshot, source: DraggableLocation) => (
<div {...provided.draggableProps} {...provided.dragHandleProps}>
Dragging over {snapshot.draggingOver}
</div>
)}
>
{({provided: DroppableProvided} => (
// 3rd party virtual list solution
<VirtualList
height={150}
itemCount={1000}
itemSize={35}
width={300}
innerRef={provided.innerRef}
>
{YourDraggableItem}
{/* provided.placeholder is not required */}
</List>
)}
</VirtualDroppable>
);
@alexreardon — Wow. Myself and @jpsear are so excited to try this! Really awesome progress. Please let me know if / when you would like some testers, we'd be happy to help.
I have created a Github project to track the details of this
@tjramage i will let you know when I get closer. I hope to do a number of beta releases
@alexreardon, awesome! Thanks for making your progress so transparent with the Github project, it's really great to see 🙏
@alexreardon Thank you thank you for making progress on this. The organization, discourse, and transparency of how this project is run...its inspiring. Also the use of emojis is 🔥
I am deciding whether to try and auto-detect if a list is a virtual list or whether to use a mode="virtual" prop on Droppable.
react-window, react-virtualised and react-tiny-virtual-list all use the same technique:
position:absolute on each list item with a top/left property to control it's initial poisitionmode approach has setup footgunsI am exploring an attempt to treat align the behaviour of virtual lists and standard lists so that no mode / auto detection is required. I am spiking this today
What thing would break if the list is not virtual? Because that means that a list without many items (no need for scroll, or only just a bit of scroll but all items are rendered) is broken upon render.
I'm putting my bets on mode="virtual" with a big big big ⚠️⚠️⚠️WARNING⚠️⚠️⚠️ expressing any concerns in the docs. And a detector for dev mode if the list isn't virtual.
12.0.0-alpha.2 is now out which contains the first cut of virtual list support. There are no docs yet - you will need to take a look a stories/virtual if you want to see how to set it up
Thanks @alexreardon! I'm looking forward to being able to use the VL support.
A question related to VLs in the meanwhile - Right now we have our own custom virtual list implementation which adds/removes elements (including draggables and droppables) on scroll (a calendar grid in which each day on the calendar is a droppable and each day can include many draggable items). Unless I missed something, it appears that adding droppables during a drag operation causes the library to throw. Is it correct to assume this behavior will be fixed/changed with VL support, and if so, is there a way to disable autoscroll in the meanwhile? (edit: we DO want the autoscroll feature, though, once it works with VLs that add droppables).
@rbudnar — I also can't make proper use of virtualised lists unless it's also possible to mount/unmount droppables during a drag operation... 😭 https://github.com/atlassian/react-beautiful-dnd/issues/1317#issuecomment-504085329
@alexreardon — do you think this would ever be technically feasible and, if so, do you plan to add in support for this at some point?
It should be technically feasible as long as a few rules are followed
Ahh that's good to know, thanks @alexreardon. It would definitely make the virtual list API a million times more useful for me, and a few others, by the sounds of it.
Wish I could buy you a beer!
Hello, I am fairly new to this library but it is very useful and beautiful, I have a column which has more than 2k cards and I want to use this can you please point me the document where I can get some info about it. I was not able to find stories/virtual.
Also If I use without virtual list it takes some second to lift the card will it be resolved by using virtual-list?
Hello I tried the above provided code snippet and got the below error

@UmangThapliyal are you using version 12.0.0-alpha.2? The virtual list support API hasn't been officially released yet, but is currently in alpha version at the version string I mentioned above.
See more details here: https://github.com/atlassian/react-beautiful-dnd/issues/1317
@UmangThapliyal are you using version
12.0.0-alpha.2? The virtual list support API hasn't been officially released yet, but is currently in alpha version at the version string I mentioned above.See more details here: #1317
Yes I was trying out 12.0.0-alpha.2 and faced the issue
Will this increase performance for @atlaskit/tree?
Latest alpha: 12.0.0-alpha.7
Latest alpha:
12.0.0-alpha.7
Does it support autosizer and items having different sizes
Untested, but should be fine 🤞
Untested, but should be fine 🤞
Thanks will check it out
VirtualDroppable will work in 12.0.0-alpha.7?
VirtualDroppable is not a thing. Use this:
<Droppable
droppableId="droppable"
mode="VIRTUAL"
whenDraggingClone={(
provided: DraggableProvided,
snapshot: DraggableStateSnapshot,
source: DraggableLocation,
) => React.Node}
>
</Droppable
VirtualDroppableis not a thing. Use this:<Droppable droppableId="droppable" mode="VIRTUAL" whenDraggingClone={( provided: DraggableProvided, snapshot: DraggableStateSnapshot, source: DraggableLocation, ) => React.Node} > </Droppable
Oh thanks I was trying with this only but reading the above comment I got the doubt thanks will try it.
Docs have not been written for this part yet
Docs have not been written for this part yet
Yeah, I was trying the example from stories/virtual, will try it out more and will post back if have any doubts.
BTW kudos for such a great library it is really helpful
@alexreardon How long will the official version be released? I can't wait to use this great feature
@alexreardon look forward to your reply
I am trudging through some issues that have been raised in testing. No firm eta at this point. I hope to have a new alpha out soon
@alexreardon can you help to understand how exactly dnd is working with virtualization? I am using react-dnd & react-window in my project and trying to simulate the same.
I wanna know what is the thought process to make support dnd with virtualization?
Thanks in advance.
I hope to do a talk about the how later. It has been a large journey
@alexreardon I have already gone through virtual-lists patterns doc. It's very useful as a user of rbd. I know _how_ is a big ask. But if you write some doc on _how_ , it will be very helpful and it will make independent logic, that will be beyod rbd.
Thanks, I will wait for _how_ doc.
Hi, is there any API about the Persistent
Hi, is there any API about the Persistent
I'm not sure what this means
Persistent?
We could get away from needing a clone if we could mark an item in a virtual list as persistent after a drag starts so the react component is never unmounted.
Just this
Using Persistent is fine. Not every major virtual list library out there supports that feature so I didn't lean on it
@alexreardon You mentioned in this issue #216 that you will support clone mode. And I think RBD‘s core is drag and drop🤣, most dnd libraries support this ability
We'll track dragging a copy in #216
This shipped in #1487 !
Most helpful comment
Whiteboarding the event listener problem with @kangweichan