如何让MUI Autocomplete提交时返回国家ID而非名称?
问题:MUI Autocomplete 结合 react-hook-form 提交时获取国家ID而非名称
我使用MUI的Autocomplete组件开发表单,结合react-hook-form处理提交,但提交后console输出的是国家名称,而我需要的是国家ID。后端返回的国家数据结构为:{"id":1,"country":"United Kingdom","symbol":"uk"}。尝试用onChange配合setValue修改表单值,但没生效,想实现类似普通select组件那样,显示名称但提交ID的效果。
原代码如下:
const Profile = () => { const { register, handleSubmit, setValue, formState: { errors }, } = useForm({}); const [countries, setCountries] = useState([]); const submit = async (value) => { console.log(value); console.log(value.countries); }; useEffect(() => { axios.get("get-countries").then((data) => { setCountries(data.data); }); }, []); return ( <> <form method="post" onSubmit={handleSubmit(submit)}> {categories.countries && ( <Autocomplete id="country-select-demo" options={categories.countries} autoHighlight getOptionLabel={(option) => option.country} renderOption={(props, option) => ( <Box component="li" sx={{ "& > img": { mr: 2, flexShrink: 0 } }} {...props} > <img loading="lazy" width="20" src={`https://flagcdn.com/w20/${option.symbol.toLowerCase()}.png`} srcSet={`https://flagcdn.com/w40/${option.symbol.toLowerCase()}.png 2x`} alt="" /> {option.country} </Box> )} renderInput={(params) => ( <TextField {...params} label="Country" inputProps={{ ...params.inputProps, autoComplete: "country", }} {...register("country", { required: true, })} /> )} onChange={(e, value) => setValue("country", value?.id)} /> )} <Button variant="contained" type="submit" sx={{ marginTop: 3 }}> Submit </Button> </form> </> ); };
解决方案
核心问题是直接给TextField绑定register会让react-hook-form捕获Autocomplete的显示值(国家名称),而非需要的ID。正确做法是用react-hook-form的Controller组件包裹Autocomplete,统一管理表单值同步:
- 从react-hook-form解构出
control和Controller - 用
Controller包裹Autocomplete,指定表单字段名"country" - 通过
Controller的render属性,用field对象同步表单状态:- 选中选项时,将选项的
id传给表单 - 从表单获取当前ID,匹配对应国家对象作为Autocomplete的选中值
- 选中选项时,将选项的
- 配置
getOptionSelected,通过ID判断选中项,确保Autocomplete正确识别选中状态
修改后的完整代码
import { Controller } from "react-hook-form"; // 其他导入保持不变 const Profile = () => { const { handleSubmit, control, formState: { errors }, } = useForm({}); const [countries, setCountries] = useState([]); const submit = async (value) => { console.log(value); // 现在输出的country是ID,比如1 }; useEffect(() => { axios.get("get-countries").then((data) => { setCountries(data.data); }); }, []); return ( <> <form method="post" onSubmit={handleSubmit(submit)}> {countries.length > 0 && ( <Controller name="country" control={control} rules={{ required: true }} render={({ field }) => ( <Autocomplete id="country-select-demo" options={countries} autoHighlight getOptionLabel={(option) => option.country} getOptionSelected={(option, value) => option.id === value.id} renderOption={(props, option) => ( <Box component="li" sx={{ "& > img": { mr: 2, flexShrink: 0 } }} {...props} > <img loading="lazy" width="20" src={`https://flagcdn.com/w20/${option.symbol.toLowerCase()}.png`} srcSet={`https://flagcdn.com/w40/${option.symbol.toLowerCase()}.png 2x`} alt="" /> {option.country} </Box> )} renderInput={(params) => ( <TextField {...params} label="Country" inputProps={{ ...params.inputProps, autoComplete: "country", }} error={!!errors.country} helperText={errors.country ? "Country is required" : ""} /> )} onChange={(e, selectedOption) => { field.onChange(selectedOption?.id); }} value={countries.find(country => country.id === field.value) || null} /> )} /> )} <Button variant="contained" type="submit" sx={{ marginTop: 3 }}> Submit </Button> </form> </> ); };
关键说明
Controller是react-hook-form专门适配第三方UI组件的工具,能精准同步组件状态与表单状态getOptionSelected必须配置,否则Autocomplete无法通过ID匹配到对应的选项对象- 原代码中
categories.countries为笔误,改为countries(与useState存储的变量一致) - 错误提示通过
errors.country控制,保持与react-hook-form的错误状态统一
内容的提问来源于stack exchange,提问作者sadasdadssad
相关产品推荐
相关产品推荐

