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

React Hook Form嵌套Controller是否可行?TypeScript报错解决

React Hook Form嵌套Controller及TypeScript错误修复

核心问题解答

  1. 嵌套Controller是否允许?
    是的,React Hook Form允许在Controller的render回调中嵌套另一个Controller,但每个Controller必须对应表单的独立字段。你的代码中两个Controller都使用name="isMovie",会导致表单状态混乱,属于错误用法。

  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 00:48:26