繁体   English   中英

Material-UI Select 组件与自定义子项

[英]Material-UI Select component with custom children item

我正在尝试创建一个Select组件,其中包含一系列通过列表映射的自定义项目。 每个项目都有特定的类型,并且基于该类型,菜单项将具有特定的 Material-UI 图标。 我创建了一个特定组件来管理整个Select组件和另一个特定组件来显示每个项目、它的值和它的图标。 问题是,每当我单击其中一项时,都不会触发onChange function。 问题可能是什么?

我附上了我正在做的事情的代码。

const myTypes = {
  TYPE_1: "Type 1",
  TYPE_2: "Type 2",
  TYPE_3: "Type 3",
};

function TypeSelect(props) {
  const classes = useStyles();
  const [state, setState] = useState(myTypes.TYPE_1);

  const onChangeType = (e) => {
    setState(e.target.value);
  };

  return (
    <Select
      id="select-type"
      value={state}
      onChange={onChangeType}
    >
      {Object.keys(myTypes).map((type) => (
        <TypeSelectMenuItem
          type={myTypes[type]}
          key={type}
        />
      ))}
    </Select>
  );
}

function TypeSelectMenuItem({ type }) {
  const renderIcon = () => {
    switch (type) {
      case myTypes.TYPE_1:
        return <ShortTextIcon />; // Material-UI icon
      case myTypes.TYPE_2:
        return <SubjectIcon />; // Material-UI icon
      case myTypes.TYPE_3:
        return <RadioButtonCheckedIcon />; // Material-UI icon
      default:
        return <Fragment />;
    }
  };

  return (
    <MenuItem value={type} >
      <ListItemIcon>{renderIcon()}</ListItemIcon>
      <ListItemText primary={type} />
    </MenuItem>
  );
}

根据 Material-UI文档,这是使用MenuItem组件呈现Select选项的方式:

<Select value={age} onChange={handleChange}>
  <MenuItem value={10}>Ten</MenuItem>
  <MenuItem value={20}>Twenty</MenuItem>
  <MenuItem value={30}>Thirty</MenuItem>
</Select>

当您想将自定义组件而不是MenuItem作为Select子项传递时。 例如TypeSelectMenuItem ,你需要做以下事情:

1. 将所有道具传递给您的自定义项目组件

SelectInput将克隆每个孩子并在场景后面附加额外的事件处理程序作为额外的道具,因此请确保使用传播运算符传递所有这些:

const TypeSelectMenuItem = (props) => {
  return (
    <MenuItem {...props}>
      {...}
    </MenuItem>
  );
};
<Select value={state} onChange={onChangeType}>
  {Object.keys(myTypes).map((type) => (
    <TypeSelectMenuItem value={myTypes[type]} key={type}>
      {myTypes[type]}
    </TypeSelectMenuItem>
  ))}
</Select>

2.将option值传递给value props

不要像你在这里所做的那样发明一个新的道具名称:

<TypeSelectMenuItem type={myTypes[type]} key={type} />

正确的方法是传递给value而不是type props:

<TypeSelectMenuItem value={myTypes[type]} key={type} />

原因是因为在内部, SelectInput引用props.value而不是您的props.type 看到这个这个 使用props.value以外的任何东西都会导致意外行为。

3. 在您的自定义组件中引用data-value而不是value

克隆项目元素时, SelectInput value props 设置为 undefined 并改用data-value props,因此您需要在内部使用data-value props:

const TypeSelectMenuItem = (props) => {
  // when passing as children item of Select. props.value is set to undefined.
  // Use props['data-value'] instead.
  return (
    <MenuItem {...props}>
      {...}
      <ListItemText primary={props["data-value"]} />
    </MenuItem>
  );
};

4. 将子项传递给您的自定义项组件以呈现选定的值

SelectInput使用子道具来呈现选定的值,因此您需要确保将某些内容作为子项传递以显示:

const TypeSelectMenuItem = (props) => {
  return (
    <MenuItem {...props}>
      // this is children of MenuItem, so it is not displayed as selected value
      <ListItemIcon>{renderIcon()}</ListItemIcon>
      <ListItemText primary={props["data-value"]} />
    </MenuItem>
  );
};
<Select value={state} onChange={onChangeType}>
  {Object.keys(myTypes).map((type) => (
    <TypeSelectMenuItem value={myTypes[type]} key={type}>
      // this is children of TypeSelectMenuItem, so it is displayed as selected value
      {myTypes[type]}
    </TypeSelectMenuItem>
  ))}
</Select>

现场演示

编辑 66943324/material-ui-select-component-with-custom-children-item

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM