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

Material UI Autocomplete集成react-hook-form时值更新异常

问题排查结论

你的代码存在3个核心问题导致删除Chip时表单值不同步:

  • 存在重复状态源:同时使用React本地状态selectedItems和react-hook-form字段值存储选中项,两个状态未做双向同步,删除自定义Chip时仅更新了本地状态,未调用react-hook-form的onChange方法更新表单值
  • Autocomplete事件逻辑错误:多选模式下MUI Autocomplete的onChange回调第二个参数是全量最新选中项数组,原代码仅取数组最后一项做追加,且调用表单onChange时传入的是闭包缓存的旧状态值,无法正确同步新增操作
  • 组件值绑定错误:Autocomplete的value属性绑定了本地状态而非react-hook-form管理的表单值,组件状态完全脱离表单管控
修复方案

遵循单一数据源原则,移除冗余的本地selectedItems状态,直接以react-hook-form维护的字段值作为唯一选中状态源,所有选中、删除操作直接同步更新表单值,外部自定义Chip直接读取表单值渲染即可。
需要修改的点:

  • 删除本地useState维护的selectedItems状态
  • 自定义Chip删除逻辑中,过滤掉待删除项后直接调用表单的onChange方法同步新值
  • 修正Autocomplete的onChange逻辑,直接将MUI返回的全量选中数组传给表单onChange
  • Autocomplete的value属性直接绑定react-hook-form注入的字段值
  • 给Controller添加数组默认值,避免首次渲染时值为undefined抛出异常
修复后完整代码
import React from 'react';
import { Autocomplete, Chip, FormControl, FormLabel, Stack, TextField } from '@mui/material';
import { Controller } from 'react-hook-form';
import CloseIcon from '@mui/icons-material/Close';

export default function FormAutoComplete({ name, control, label, error, options, ...props }) {
  return (
    <FormControl fullWidth>
      <FormLabel>{label}</FormLabel>
      <Controller
        name={name}
        control={control}
        defaultValue={[]}
        render={({ field: { onChange, value = [] } }) => {
          // 直接读取表单值渲染外部自定义Chip
          const selectedItemChip = value.map((item) => {
            return (
              <Chip
                key={item}
                label={item}
                deleteIcon={<CloseIcon />}
                onDelete={() => {
                  // 删除操作直接同步更新表单值
                  const newValue = value.filter((entry) => entry !== item);
                  onChange(newValue);
                }}
              />
            );
          });

          return (
            <>
              <Autocomplete
                multiple
                filterSelectedOptions
                options={options}
                getOptionLabel={(option) => option}
                // 隐藏组件内置标签,使用外部自定义Chip
                renderTags={() => {}}
                // 直接绑定表单维护的选中值
                value={value}
                // 选中选项时直接同步全量最新值到表单
                onChange={(_, newValue) => {
                  onChange(newValue);
                }}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    {...props}
                    error={!!error}
                    helperText={error?.message}
                  />
                )}
              />
              <Stack direction="row" marginTop={2} gap={1} flexWrap="wrap">
                {selectedItemChip}
              </Stack>
            </>
          );
        }}
      />
    </FormControl>
  );
}

// 业务使用时可直接传入自定义选项,也可使用默认选项
export const defaultOptions = [
  'Building Materials',
  'Tools',
  'Decor & Furniture',
  'Bath',
  'Doors & Windows',
  'Cleaning',
  'Electrical',
  'Heating & Cooling',
  'Plumbing',
  'Hardware',
  'Kitchen',
  'Lawn & Garden',
  'Lighting & Fans',
];

修复后选中、删除操作都会实时同步react-hook-form的字段值,配置的「至少选择1项」校验规则可以正常触发,Autocomplete的已选项过滤逻辑也会和外部Chip状态保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:15:43