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

React-Hook-Form v7:禁用字段时如何跳过Controller组件验证

问题描述

我正在使用react-hook-form搭配@mui/material开发,需要将MUI的TextField组件通过render属性传入react-hook-form的Controller组件中。
我期望当TextField处于禁用状态时,该字段的验证规则能自动跳过,但目前无论是否禁用,验证都会触发,导致禁用字段显示错误提示。
不使用Controller、直接用register时,<input {...register('someField', {disabled: true})}/>可以正常跳过验证,但我需要在使用Controller组件的场景下实现同样效果。

已尝试方案
  • 仅为字段添加disabled属性
<Controller
            name="secondField"
            control={control}
            shouldUnregister={true}
            //rules={{required:true}}
            render={({
              field: { onChange, value, ref },
              fieldState: { error },
              formState
            }) => {
              console.log(error);
              let commonFieldVal = watch("commonTextField");
              //let isDisabled = commonFieldVal === "bob";

              return (
                <TextField
                  label="secondField"
                  disabled={true}
                  error={!!error}
                  value={value}
                  onChange={onChange}
                  ref={ref}
                />
  • 为字段添加shouldUnregister属性

完整代码示例

import {
  useForm,
  Controller,
  ControllerFieldState,
  ControllerRenderProps,
  FieldValues,
  UseFormStateReturn
} from "react-hook-form";
import { TextField, Button, Box } from "@mui/material";
import { useEffect, useState } from "react";

import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

let CommonTextField = ({ error, value, onChange, setSecondFormState }) => {
  let isDisabled = value === "bob";
  useEffect(() => {
    setSecondFormState(isDisabled);
  }, [isDisabled]);
  return (
    <TextField
      label="commonTextField"
      error={!!error}
      value={value}
      onChange={onChange}
    />
  );
};
/////////////////////////////////
const schema = yup.object({
  commonTextField: yup.string().required("commonTextField is required"),
  secondField: yup.string().required("secondField is required")
});
/////////////////////////////////
export default function App() {
  /////////////////////////////
  //  useForm
  let {
    handleSubmit,
    watch,
    reset,
    formState,
    setValue,
    control,
    getValues,
    getFieldState,
    register,
    unregister
  } = useForm({
    defaultValues: { commonTextField: "", secondField: "" },
    shouldUnregister: true,
    resolver: yupResolver(schema)
  });

  let { errors } = formState;
  let [secondFormIsDisabled, setSecondFormState] = useState(false);
  console.log(errors);
  return (
    <form
      onSubmit={handleSubmit((data) => {
        console.log("Succes Submit FORM DATA----->> ", data);
        reset();
      })}
    >
      <Box sx={{ display: "flex", flexDirection: "column", gap: "10px" }}>
        <Controller
          name="commonTextField"
          control={control}
          render={({
            field: { onChange, value },
            fieldState: { error },
            formState
          }) => {
            console.log(error);

            return (
              <CommonTextField
                error={!!error}
                value={value}
                onChange={onChange}
                setSecondFormState={setSecondFormState}
              />
            );
          }}
        />

        {!secondFormIsDisabled && (
          <Controller
            name="secondField"
            control={control}
            shouldUnregister={true}
            //rules={{required:true}}
            render={({
              field: { onChange, value, ref },
              fieldState: { error },
              formState
            }) => {
              console.log(error);
              let commonFieldVal = watch("commonTextField");
              //let isDisabled = commonFieldVal === "bob";

              return (
                <TextField
                  label="secondField"
                  disabled={secondFormIsDisabled}
                  error={!!error}
                  value={value}
                  onChange={onChange}
                  ref={ref}
                />
              );
            }}
          />
        )}
      </Box>
      <Button type="submit">SUBMIT</Button>
    </form>
  );
}
临时解决办法

移除Yup验证,将验证规则转移到react-hook-form的rules中,当需要显示禁用字段时,通过条件渲染区分:

{!secondFormIsDisabled ? (
          <Controller
            name="secondField"
            control={control}
            shouldUnregister={true}
            rules={{required:true, ...secondFieldValidation}}
            render={({
              field: { onChange, value, ref },
              fieldState: { error },
              formState
            }) => {
              console.log(error);
              //let commonFieldVal = watch("commonTextField");
              //let isDisabled = commonFieldVal === "bob";

              return (
                <TextField
                  label="secondField"
                  
                  error={!!error}
                  value={value}
                  onChange={onChange}
                  ref={ref}
                />
              );
            }}
          />
        ): <TextField disabled={secondFormIsDisabled} />}

内容的提问来源于stack exchange,提问作者scad scad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:43:13