mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.36k stars 32.13k forks source link

[Select] getting slow when loading 2000 options #17001

Open gopinath-sixt opened 5 years ago

gopinath-sixt commented 5 years ago

Current Behavior 😯

Expected Behavior 🤔

Need to be fast on showing the drop-down and selecting the value

Steps to Reproduce 🕹

https://codesandbox.io/s/material-demo-5ygxr

Your Environment 🌎

Tech Version
Material-UI v4.3.2
React 16.9.1
Browser chrome
etc.
mbrookes commented 5 years ago

That's to be expected. You need to use a virtualisation solution, perhaps following this example: https://material-ui.com/components/lists/#virtualized-list

devsumanmdn commented 5 years ago

That's to be expected. You need to use a virtualisation solution, perhaps following this example: https://material-ui.com/components/lists/#virtualized-list

@mbrookes with a usual virtualisation solution we'll lose full keyboard interactivity. For example, we'll not be able to type an option's text to move the focus. Is it possible to tweak something and have full keyboard interactivity with a virtualisation solution?

mbrookes commented 5 years ago

You might have to use the native select in that case: https://material-ui.com/components/selects/#native-select

gopinath-sixt commented 5 years ago

Hi @oliviertassinari

Thanks for adding as Enhancement, we are waiting for upcoming release.

@mbrookes : By using native-select, options will not come in material design but we are expecting the performance in material-ui-select.

eps1lon commented 5 years ago

That's to be expected. You need to use a virtualisation solution, perhaps following this example: https://material-ui.com/components/lists/#virtualized-list

@mbrookes with a usual virtualisation solution we'll lose full keyboard interactivity. For example, we'll not be able to type an option's text to move the focus. Is it possible to tweak something and have full keyboard interactivity with a virtualisation solution?

It's one of the reasons why I prefer <Select options={[options]} /> + renderprops APIs. While a declarative API looks nice for few options it just doesn't scale for multiple options or custom renderers with type-ahead support. It's also much friendlier to types which would probably negate the reduced DX from using renderprops.

This applies essentially to all collection widgets (trees, lists and grids). I'll take a look at the current keyboard a11y implementation and how you would add virtualization to Select.

KenNguyen-0107 commented 4 years ago

That's to be expected. You need to use a virtualisation solution, perhaps following this example: https://material-ui.com/components/lists/#virtualized-list

@mbrookes with a usual virtualisation solution we'll lose full keyboard interactivity. For example, we'll not be able to type an option's text to move the focus. Is it possible to tweak something and have full keyboard interactivity with a virtualisation solution?

It's one of the reasons why I prefer <Select options={[options]} /> + renderprops APIs. While a declarative API looks nice for few options it just doesn't scale for multiple options or custom renderers with type-ahead support. It's also much friendlier to types which would probably negate the reduced DX from using renderprops.

This applies essentially to all collection widgets (trees, lists and grids). I'll take a look at the current keyboard a11y implementation and how you would add virtualization to Select.

Hi @eps1lon,

did you have the time to checkout the implementation of virtualization to Select (either using React-Window or React-Virtualized).

My problem is pretty similar to this post here: https://stackoverflow.com/questions/57799541/unable-to-select-item-when-using-textfield-or-select-with-react-window/60258515#60258515

eps1lon commented 4 years ago

did you have the time to checkout the implementation of virtualization to Select (either using React-Window or React-Virtualized).

Sorry, I didn't have time for it. Doesn't look like I will have bandwidth for this during OSS time in the near future.

rvighnes commented 3 years ago

https://material-ui.com/components/autocomplete/#virtualization

mogadanez commented 3 years ago

virtualization is good, but anyway concerning with overhead in performance I have list of ~800 items

{list.map(s=>{
                      return <Fragment key={s.mediaID}>
                             <div className={classes.someClass}>{s.title}</div>
                        </Fragment>
                  }) }
{list.map(s=>{
                      return <Fragment key={s.mediaID}>
                             <Typography className={classes.someClass}>{s.title}</div>
                        </Typography>
                  }) }

the difference in execution time is 6-7 times. if use ListItem instead of Typography, difference will be up to x20 times

UnderTheMoonspell commented 3 years ago

Will this ever be fixed? Ive researched around and the only solutions seem to be using virtualization with Autocomplete, which is not a Select (and Ive tried to make the Autocomplete work as a select by disabling typing, but could not make it work), so its really not a solution.

oliviertassinari commented 3 years ago

@UnderTheMoonspell we might rebuild the select to solve this and a dozen other issues we have with the component.

ItayTur commented 2 years ago

does this has a fix in the latest version? or a workaround ? I build an entire new component on top of the Select, and now using it for the first with 2000 options and it is laggy.

m0onspell commented 2 years ago

@UnderTheMoonspell 🤟

m0onspell commented 2 years ago

So basically there's no way to integrate any virtualization solution with non-native Select component? I am not asking about List or Autocomplete. Select requires you to pass MenuItem as direct descendants, so as the result you can't wrap them in say FixedSizeList from react-window. Is there some way around it?

maryannabt commented 1 year ago

@oliviertassinari Hello! Are there any updates on this issue? Regarding of virtualization in Select component specifically.

gkiely commented 9 months ago

For anyone looking into this further, the issue is the following:

MenuItem uses MenuItemRoot, MenuItemRoot is generated by styled which is calling createStyled. createStyled returns a jsx element that also does CSS processing for each react node, which it looks like is causing the slowdown.

  1. https://github.com/mui/material-ui/blob/master/packages/mui-material/src/MenuItem/MenuItem.js#L50
  2. https://github.com/mui/material-ui/blob/master/packages/mui-material/src/styles/styled.js
  3. https://github.com/mui/material-ui/blob/master/packages/mui-system/src/createStyled.js#L132

You can get a high performance and functional list with no styles by replacing MenuItemRoot in MenuItem.js.

const MenuItemRoot = /*#__PURE__*/React.forwardRef(function MenuItemRoot({ focusVisibleClassName, ownerState, ...props }, ref) {
  if(props.component.render){
    return props.component.render(props);
  }
  return React.createElement("li", { ref, ...props });
});

** It requires implementing your own styles, theming, closing the menu. But the focus and scrolling works as expected and it is high performance.

If the maintainers are open to it I can expand on the above and open a PR with a MenuItemUnStyled or something similar.

Video of the existing MenuItem with 2000 rows. https://www.loom.com/share/fa97283e34f443f0b1179a0131cd0e33

Video of MenuItem after the changes above. https://www.loom.com/share/5b22d317037442e997c3b5fb944a290e