MUI异步Autocomplete配合react-hook-form时表单无法获取组件值
问题原因
- 你在封装
AddressInput组件时重复维护了两份选中值状态:一份是react-hook-form通过Controller管理的表单状态,另一份是组件内部用useState声明的value状态。你自定义的Autocomplete的value和onChange属性覆盖了field对象自带的对应属性,导致选中地址时只更新了组件内部状态,没有同步给react-hook-form的表单实例,所以提交时获取到的data.address始终为undefined。 - 组件内部维护的
value状态和react-hook-form的表单状态完全割裂,没有同步逻辑,外层表单自然无法拿到选中值。
解决方法
直接修改AddressInput组件逻辑,移除冗余的内部选中值状态,将值同步逻辑交给react-hook-form处理,修改后的核心代码如下:
const AddressInput = ({ control, name, ...rest }) => { const [inputValue, setInputValue] = React.useState(""); const [options, setOptions] = React.useState([]); const fetch = React.useMemo( () => throttle((request) => { const getData = getAddress(request?.input); getData.then((res) => { setOptions(JSON.parse(res)?.candidates); return JSON.parse(res).candidates; }); }, 200), [] ); return ( <Controller name={name} control={control} defaultValue={null} render={({ field }) => { React.useEffect(() => { let active = true; if (inputValue === "") { setOptions(field.value ? [field.value] : []); return undefined; } fetch({ input: inputValue }, (results) => { if (active) { let newOptions = []; if (field.value) { newOptions = [field.value]; } if (results) { newOptions = [...newOptions, ...results]; } setOptions(newOptions); } }); return () => { active = false; }; }, [field.value, inputValue, fetch]); return ( <Autocomplete {...field} id="address" getOptionLabel={(option) => typeof option === "string" ? option : option.address } filterOptions={(x) => x} options={options} autoComplete includeInputInList filterSelectedOptions value={field.value} onChange={(event, newValue) => { console.log(newValue); setOptions(newValue ? [newValue, ...options] : options); // 同步选中值到react-hook-form field.onChange(newValue); }} onInputChange={(event, newInputValue) => { setInputValue(newInputValue); }} renderInput={(params) => ( <TextField {...rest} {...params} variant="outlined" fullWidth /> )} renderOption={(option) => <span>{option.address}</span>} /> ) }} /> ); };
修改后所有原本用到内部value的地方都替换为field.value,选中值变更时主动调用field.onChange同步给表单实例,提交时就能拿到正确的address值。
内容的提问来源于stack exchange,提问作者aadlc
相关产品推荐
相关产品推荐

