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

React Material UI 如何根据关联值自动移除Autocomplete已选项

问题描述

基于 Material UI Autocomplete 组件开发两级联动多选框,参考官方复选框用法实现,需要解决主分类取消选中时,对应已选子分类自动清除的联动问题,具体边界场景:

  • 主行业选择框同时选中「Consumer Electronics」「Fashion & Apparel」两个选项
  • 子行业选择框分别选中两个主分类下的子项:Consumer Electronics 下的「Computer & Laptops」、Fashion & Apparel 下的「Eyewear」
  • 后续在主行业选择框移除「Fashion & Apparel」时,子行业选择框中所有归属该分类的已选子项需要同步自动移除

功能效果截图:两级联动选择框效果
在线可运行示例:CodeSandbox Demo

当前子行业选择框已经通过filterOptions实现选项过滤,仅展示和已选主行业匹配的子行业选项,原始数据结构可查看示例项目中的data.json,现有子行业选择框核心代码如下:

return (
  <Autocomplete
    multiple
    options={subIndustries}
    filterOptions={(x) =>
      x.filter((x) =>
        getValues("main_industries").find((m) => m.name === x.category)
      )
    }
    groupBy={(option) => option.category}
    disableCloseOnSelect
    getOptionLabel={(option) => option.name}
    onChange={(_, newValue: any) => {
      setValue("sub_industries", newValue, { shouldValidate: true });
    }}
    defaultValue={getValues("sub_industries")}
    onInputChange={(_, val) => {
      console.log(val);
    }}
    renderOption={(props, option, { selected }) => (
      <li {...props}>
        <Checkbox
          icon={uncheckedIcon}
          checkedIcon={checkedIcon}
          style={{ marginRight: 8 }}
          checked={selected}
        />
        {option.name}
      </li>
    )}
    renderInput={(params) => (
      <TextField
        {...params}
        label="Sub Industries"
        placeholder="Sub Industries"
      />
    )}
  />
);
实现方案

核心逻辑是监听主行业选中值的变化,每次主行业选中项变更时,自动校验已选子行业的合法性,剔除所属主行业已被取消选中的子项即可。

  1. 监听表单中main_industries字段的变化
  2. 主行业选中项更新后,过滤当前已选的子行业列表,仅保留所属分类存在于最新主行业选中列表中的子项
  3. 将过滤后的合法子项更新到sub_industries表单字段,同步更新组件视图
  4. 将子行业Autocomplete从非受控改为受控模式,避免表单值和视图展示不一致

核心代码

// 监听主行业选中值变化
const selectedMainIndustries = watch("main_industries");

useEffect(() => {
  const currentSubList = getValues("sub_industries") || [];
  // 过滤掉归属主行业已被移除的子项
  const validSubList = currentSubList.filter(subItem => 
    selectedMainIndustries.some(mainItem => mainItem.name === subItem.category)
  );
  // 更新子行业字段值,触发校验
  setValue("sub_industries", validSubList, { shouldValidate: true });
}, [selectedMainIndustries, getValues, setValue]);

调整子行业Autocomplete的属性,将原来的defaultValue替换为受控的value绑定,保证值同步:

<Autocomplete
  multiple
  options={subIndustries}
  // 替换defaultValue为受控value绑定
  value={watch("sub_industries") || []}
  filterOptions={(options) =>
    options.filter(opt =>
      selectedMainIndustries.some(main => main.name === opt.category)
    )
  }
  groupBy={(option) => option.category}
  disableCloseOnSelect
  getOptionLabel={(option) => option.name}
  onChange={(_, newValue) => {
    setValue("sub_industries", newValue, { shouldValidate: true });
  }}
  // 其余原有属性(renderOption、renderInput等)保持不变
  // ...
/>

内容的提问来源于stack exchange,提问作者Kay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:51:32