Blueprint: Virtualize QueryList items

Created on 28 Jun 2018  路  9Comments  路  Source: palantir/blueprint

Environment

Feature request

It would be great to have the Select list elements, or the QueryList for that matter, be virtualized to let it handle very long lists.

Examples

I wanted to use Select to handle a list with ~1400 elements, with just a span inside, and as it renders all the items the list takes a good while to appear and filter. I ended up piecing something with react-tiny-virtual-list and Popover2, but without a bunch of the capabilities of Select.

in discussion feature request

Most helpful comment

I believe it's something to do with the style parameter of renderItem from VirtualList.

  renderSelectList = ({
    items,
    itemsParentRef, // do i need this??
    renderItem,
  }: {
    items: Films.IFilm[],
    itemsParentRef: (ref: HTMLElement | null) => void,
    renderItem: (item: any, index: number) => JSX.Element | null,
  }) => {
    return (
      <VirtualList
        width="100%"
        height={400}
        itemCount={items.length}
        itemSize={20} // Also supports variable heights (array or function getter)
        renderItem={({ index, style }) => renderItem(items[index], index)}
      />
    );
  };

I think you're right, as I'm having a similar problem with a different virtualized list library.

Many of the virtualized/window libraries work by setting absolute positions on the elements in the list as you scroll. (This blank list effect is a very common scenario)

Because the renderItem(..) method does not accept them, we cannot pass the style props through to the <MenuItem/> component being rendered.


I've got something working here, but the styling is a bit off.
https://codesandbox.io/s/wandering-meadow-7szg0

All 9 comments

@frabarz this is precisely what itemListRenderer is for. we don't want to add a dep on a virtualized library so we added a hook for you to do it yourself!

Oh also you'll need to be on 2.x or ideally 3.0 for this

@adidahiya Thoughts on re-opening this? Using a custom itemListRenderer is actually non-trivial or impossible with the new "Create item" option. We may just need to improve the support story there, but I also think it's reasonable for the Select components to handle rendering virtualization internally.

I agree this not being trivial. I'm having issues using react-tiny-virtual-list. Could anybody provide an example or help me figure this out?:

https://codesandbox.io/s/p3j721n57m

Screenshot 2019-04-28 at 23 09 10

I believe it's something to do with the style parameter of renderItem from VirtualList.

  renderSelectList = ({
    items,
    itemsParentRef, // do i need this??
    renderItem,
  }: {
    items: Films.IFilm[],
    itemsParentRef: (ref: HTMLElement | null) => void,
    renderItem: (item: any, index: number) => JSX.Element | null,
  }) => {
    return (
      <VirtualList
        width="100%"
        height={400}
        itemCount={items.length}
        itemSize={20} // Also supports variable heights (array or function getter)
        renderItem={({ index, style }) => renderItem(items[index], index)}
      />
    );
  };

@gianpaj Would a list-style: none CSS rule come to the rescue here? The menu items look okay but for the erroneous bullets. Having not used react-tiny-virtual-list myself before, I'm not sure which selector would need that rule, but hopefully some quick DOM spelunking can help identify the right element.

Hi @cmslewis , thanks for that but actually the CSS is not the only issue.
The biggest issue is that the rest of the items are not appearing on the screen as I believe their position is not being updated when you're scrolling.
i.e. after 79. A Clockwork Orange, more films should appear.

Check the example: https://codesandbox.io/s/p3j721n57m
and gif:
May-09-2019 23-06-12

That's my guess anyway

I believe it's something to do with the style parameter of renderItem from VirtualList.

  renderSelectList = ({
    items,
    itemsParentRef, // do i need this??
    renderItem,
  }: {
    items: Films.IFilm[],
    itemsParentRef: (ref: HTMLElement | null) => void,
    renderItem: (item: any, index: number) => JSX.Element | null,
  }) => {
    return (
      <VirtualList
        width="100%"
        height={400}
        itemCount={items.length}
        itemSize={20} // Also supports variable heights (array or function getter)
        renderItem={({ index, style }) => renderItem(items[index], index)}
      />
    );
  };

I think you're right, as I'm having a similar problem with a different virtualized list library.

Many of the virtualized/window libraries work by setting absolute positions on the elements in the list as you scroll. (This blank list effect is a very common scenario)

Because the renderItem(..) method does not accept them, we cannot pass the style props through to the <MenuItem/> component being rendered.


I've got something working here, but the styling is a bit off.
https://codesandbox.io/s/wandering-meadow-7szg0

@saruman1234 That helped a lot. Thanks for sharing.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adidahiya picture adidahiya  路  18Comments

zhaoyi0113 picture zhaoyi0113  路  21Comments

isTravis picture isTravis  路  43Comments

NickyYo picture NickyYo  路  18Comments

icd2k3 picture icd2k3  路  17Comments