MUI Select组件标签显示异常:禁用时居上而非内部占位
MUI 多选Select组件禁用状态标签异常修复
问题现象
- 组件初始禁用时,标签显示在输入框轮廓上方,而非内部作为占位符,显式设置
shrink={false}无效 - 启用后点击组件(未选择内容),标签恢复到输入框中间正常显示
- 预期行为:未选中内容时(即使组件禁用)标签显示在输入框内部,选中后移至缺口位置
- 隐身模式首次加载正常,刷新后标签回到上方
异常截图

组件代码
'use client'; import TokenChips from '@components/general/TokenChips'; import { Checkbox, FormControl, ListItemText } from '@mui/material'; import InputLabel from '@mui/material/InputLabel'; import MenuItem from '@mui/material/MenuItem'; import OutlinedInput from '@mui/material/OutlinedInput'; import Select, { SelectChangeEvent } from '@mui/material/Select'; import { useEffect, useState } from 'react'; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { style: { maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, width: 250 } } }; export default function CoisDropdown({ cois, name }: { cois: string[]; name: string; }) { const [selectedCois, setSelectedCois] = useState<string[]>([]); const onCoiSelectChange = (event: SelectChangeEvent<typeof selectedCois>) => { const { target: { value } } = event; setSelectedCois( // Guard for corner case: on autofill we get a stringified value, so split into array typeof value === 'string' ? value.split(',') : value ); }; // Reset selected cois if new cois are set from parent useEffect(() => { setSelectedCois([]); }, [cois]); return ( <> <FormControl fullWidth sx={{ mt: 2 }} variant='outlined'> <InputLabel id='coi-label' shrink={false}> Select COIs </InputLabel> <Select fullWidth multiple labelId='coi-label' id={name} name={name} value={selectedCois} onChange={onCoiSelectChange} input={ <OutlinedInput label='Select COIs' /> } renderValue={(selected) => selected.join(',\u00A0\u00A0')} label='Select COIs' disabled={cois.length === 0} MenuProps={MenuProps} > {cois.map((coi) => ( <MenuItem key={coi} value={coi}> <Checkbox checked={selectedCois.includes(coi)} /> <ListItemText primary={coi} /> </MenuItem> ))} </Select> </FormControl> <div style={{ marginTop: '16px' }}> <TokenChips tokens={selectedCois} /> </div> </> ); }
解决方案
方法1:动态控制InputLabel的shrink状态
根据选中内容的长度决定是否收缩标签,替代固定的shrink={false}:
<InputLabel id='coi-label' shrink={selectedCois.length > 0}> Select COIs </InputLabel>
仅当有选中内容时,标签才会移到上方,未选中时(包括禁用状态)保持在输入框内部。
方法2:移除OutlinedInput上的冗余label属性
Select和OutlinedInput同时设置label会导致MUI内部状态冲突,只保留Select和InputLabel上的标签文本:
<Select // 其他属性不变 input={<OutlinedInput />} // 移除这里的label属性 label='Select COIs' >
方法3:CSS强制调整标签位置
如果前两种方法无效,通过自定义样式覆盖MUI的默认行为:
<FormControl fullWidth sx={{ mt: 2, '& .MuiInputLabel-root.Mui-disabled': { transform: 'translate(14px, 20px) scale(1)', '&.MuiInputLabel-shrink': { transform: 'translate(14px, -9px) scale(0.75)', } } }} variant='outlined' >
补充说明
隐身模式首次加载正常是缓存导致的MUI内部状态计算异常,上述方法可规避该问题。
内容的提问来源于stack exchange,提问作者user1902183
相关产品推荐
相关产品推荐

