React Hook Form嵌套Controller是否可行?TypeScript报错解决
React Hook Form嵌套Controller及TypeScript错误修复
核心问题解答
嵌套Controller是否允许?
是的,React Hook Form允许在Controller的render回调中嵌套另一个Controller,但每个Controller必须对应表单的独立字段。你的代码中两个Controller都使用name="isMovie",会导致表单状态混乱,属于错误用法。TypeScript lint错误修复
错误'onChange' is already declared in the upper scope是因为内层Controller的render回调参数onChange与外层重名,只需对内层参数重命名(比如innerOnChange)即可解决。
适配业务场景的正确代码示例
根据你“单选控制是否看电影,选观看则显示影片选择框”的需求,调整后的代码如下:
import { useForm, Controller } from "react-hook-form"; import { FormControl, RadioGroup, FormControlLabel, Radio, Autocomplete, TextField } from "@mui/material"; // 表单值类型定义 type FormValues = { isMovie: "WatchMovie" | "donotwatchmovie"; selectedMovie?: { value: string }; // 匹配你的影片数据结构 }; export default function MovieForm() { const { control, watch } = useForm<FormValues>({ defaultValues: { isMovie: "WatchMovie" } }); const isMovie = watch("isMovie"); return ( <FormControl> {/* 控制是否观看电影的单选组 */} <Controller control={control} id="isMovie" name="isMovie" render={({ field: { onChange, value } }) => ( <RadioGroup value={value} onChange={(event) => onChange(event.target.value)} > <FormControlLabel value="WatchMovie" control={<Radio color="primary" size="small" />} label="Select Movie to watch" /> {/* 仅选择观看时显示影片选择框 */} {isMovie === "WatchMovie" && ( <Controller control={control} id="selectedMovie" name="selectedMovie" render={({ field: { onChange: innerOnChange, value: innerValue } }) => ( <Autocomplete disablePortal // classes={{ root: classes.MuiFormControlLabel }} options={ // 根据实际逻辑切换影片列表 isMovie === "english" ? englishMovie : spanishMovie } getOptionLabel={(option) => option.value.toString()} value={innerValue} renderInput={(params) => <TextField {...params} label="Select Movie" />} onChange={(_, newValue) => innerOnChange(newValue)} /> )} /> )} <FormControlLabel value="donotwatchmovie" control={<Radio color="primary" size="small" />} label="Do Not watch a movie" /> </RadioGroup> )} /> </FormControl> ); }
关键调整说明
- 拆分独立字段:将原单一
isMovie字段拆分为isMovie(控制是否观看)和selectedMovie(存储选中影片),每个Controller对应独立字段,避免状态冲突。 - 参数重命名:内层Controller的
onChange重命名为innerOnChange,解决变量重名的TypeScript lint错误。 - 条件渲染:通过
isMovie === "WatchMovie"控制影片选择框的显示/隐藏,贴合业务逻辑。 - 规范Controller用法:使用
field解构({ field: { onChange, value } })是React Hook Form推荐写法,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Tanu
相关产品推荐
相关产品推荐

