You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 15:36:17