Closed AngelGenchev95 closed 2 years ago
@AngelGenchev95 I tried your stackblitz but I could not see the issue. Can you check?
@siriwatknp Here's a video of the issue: https://user-images.githubusercontent.com/41321846/182336688-45bc69fb-0925-4231-b62f-37202a2b9c21.mov I'm using a macbook pro, Chrome
The same issue even without Modal component.
Please see my screen record. 252 MenuItem
components were used here.
https://user-images.githubusercontent.com/5411244/183246611-5247f0f3-82e5-47b0-a08e-1d7dbf873f7d.mov
React version: 18.2 MUI version: 5.9.3
Hi there,
The reason of this behavior is a big amount of options that are rendered simultaneously when select is opening. Even with 20 - 30 options this issue becomes noticeable. If we use 1000 options, the list is rendered at the left and only after ~3 seconds moves to the proper position.
I've found a several possible solutions/ideas:
Use native
select. This is the simplest solution (just add one prop), but unfortunately options list is out of common design and it looks a little bit ugly.
Use virtualization for the options list. I tried to use Virtuoso for the options list but unfortunately I didn't find how to do it properly to don't break control with keyboard.
Use Autocomplete instead of Select. It uses virtualization inside, options renders properly. But it provides a little bit another functionality then Select, also there are visual deferences.
Render just one MenuItem component on select opening and then render all options after small delay. This solution I applied for my project. Initially I render just one MenuItem disabled component with progress bar inside. After 300ms delay all other options are rendered.
const FormPhoneNumber: FC<FormPhoneNumberProps> = ({}) =>
{
const {data: countries = []} = useGetCountriesQuery();
const [countryCode, setCountryCode] = useState<number | ''>('');
const [isOpened, setIsOpened] = useState<boolean>(false);
return (
<TextField
select
SelectProps={{
onOpen: () => setTimeout(() => setIsOpened(true), 300),
onClose: () => setTimeout(() => setIsOpened(false), 300),
renderValue: () =>
{
const item = countries.find(({phoneCode}) => countryCode === phoneCode);
return item ? getOptionLabel(item) : '';
},
}}
label="Country"
value={countryCode}
onChange={(event) => setCountryCode(Number(event.target.value))}
fullWidth
>
{!isOpened && (
<MenuItem
disabled
sx={{
opacity: '1 !important',
justifyContent: 'center',
}}
value={countryCode}
>
<CircularProgress size={20} disableShrink />
</MenuItem>
)}
{isOpened && countries.map((item) => (
<MenuItem key={item.code} value={item.phoneCode}>
{getOptionLabel(item)}
</Option>
))}
</TextField>
);
};
@AngelGenchev95, probably this solution will be also acceptable for you.
Isn't this a duplicate of #33308?
Also, this is happening to me with a Menu
component.
Yes, this is a duplicate of #33308.
Duplicates
Latest version
Current behavior 😯
Currently when we have a MUI modal that contains a MUI select with more than 100 items, the first time you open that select, the items appear glued to the left of the screen, before repositioning to their intended spot.
Expected behavior 🤔
The items should immediately appear in their intended spot, relative to the input.
Steps to reproduce 🕹
Steps:
Context 🔦
I'm trying to make a Select inside a modal that contains a list of countries.
Your environment 🌎
Working example: https://stackblitz.com/edit/react-ts-xefudx?file=App.tsx