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.96k stars 32.27k forks source link

[Select] Add virtualization support #29130

Open ItayTur opened 3 years ago

ItayTur commented 3 years ago

Material UI Select component is lagging when having more than 200 options. I try to work around it using react-virtual npm. this should solve the issue because it follows the Select rule of children can be MenuItem Only, since it provides a hook and not a wrapping component, like in react-window.

Current Behavior 😯

The overflowen options are not rendered when scrolled to them.

Expected Behavior 🤔

It should render the other options, based on the view location.

Steps to Reproduce 🕹

https://codesandbox.io/s/lucid-ritchie-j2c13?file=/src/Demo.tsx

Steps:

  1. Open the select by clicking it.
  2. scroll to the bottom.

Context 🔦

My app has dropdowns with over 2000 options in it. If the select is lagging, I can't use it. https://github.com/mui/material-ui/issues/17001

Your Environment 🌎

`npx @mui/envinfo` System: OS: macOS 11.6 Binaries: Node: 14.17.0 - /usr/local/bin/node Yarn: 1.22.10 - /usr/local/bin/yarn npm: 6.14.13 - /usr/local/bin/npm Browsers: Chrome: 94.0.4606.81 Edge: Not Found Firefox: Not Found Safari: 15.0 npmPackages: @emotion/styled: 10.0.27 @types/react: ^17.0.0 => 17.0.1 react: ^17.0.1 => 17.0.1 react-dom: ^17.0.1 => 17.0.1 styled-components: ^5.2.1 => 5.2.1 typescript: ^4.1.3 => 4.1.3 ``` Don't forget to mention which browser you used. Output from `npx @mui/envinfo` goes here. ```
mnajdova commented 3 years ago

There are a few problems with your implementation.

  1. The ref is put on the wrong element, it should be on the MenuList
  2. There should be an inner div between the elements as far as I could see on the demos - please verify if it is really required
  3. The problem of why it isn't working is because the ref you are propagating to the hook is a DOM node that is created only after the list is shown (the select is opened), so it is basically not defined at the start. You should use a callback ref there and store the node in state. See https://codesandbox.io/s/hardcore-margulis-pucxg?file=/src/Demo.tsx
ItayTur commented 3 years ago

thx for the response. Your solution is progress, yet with still few issues: 1) the select stop working - selecting any item doesn't fire onChange with the right value. I think it's because the Select children must be material ui MenuItem or Array of MenuItem 2) if i drop the inner div and move the height style to the menu-props, it shows the selected value but the input is flickering on each scroll, and no new options are rendered : https://codesandbox.io/s/silly-benji-zbd6u?file=/src/Demo.tsx:577-714

mnajdova commented 3 years ago

I haven't used the library much I must be honest, so I am pretty sure it needs more work. Also, take a look at https://mui.com/components/autocomplete/#virtualization for inspiration too.

ItayTur commented 3 years ago

thank you but it got to be the select, i can't use the autocomplete.

mnajdova commented 3 years ago

Yeah, it's unfortunate that the select uses the React.cloneElement, which is basically the problem we have here. I am marking it as a duplicate of https://github.com/mui-org/material-ui/issues/14943. This component will probably be re-written from scratch. cc @michaldudak

ItayTur commented 3 years ago

Thx again for the quick response... If I find a way to solve this ill post it here

maryannabt commented 1 year ago

@ItayTur, @mnajdova Hi! Have you found a way to solve it? :)