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
相关产品推荐
相关产品推荐

