reactjsreact-hook-formyup

How to Combine Yup Schema Validation with Custom rules in React Hook Form?


Problem:

  1. The Yup validation works fine, but the custom validation in the rules for the password field doesn't seem to execute at all.
  2. My goal is to combine both Yup validation (for schema-wide validation) and custom field-specific validation using the validate function in rules.
import React from 'react';
import { useForm, Controller, FormProvider } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';

// Yup validation schema
const LoginSchema = yup.object({
  username: yup.string().required("Username is required"),
  password: yup.string().min(8, "Password must be 8 characters long").required(),
}).required();

const InputField = ({ name, label, rules }) => {
  const { control } = useFormContext();
  return (
    <Controller
      name={name}
      control={control}
      rules={rules}
      render={({ field, fieldState: { error } }) => (
        <TextField
          {...field}
          label={label}
          error={!!error}
          helperText={error ? error.message : ""}
        />
      )}
    />
  );
};

const MyForm = () => {
  const methods = useForm({
    resolver: yupResolver(LoginSchema),
    mode: 'onChange',
    reValidateMode: 'onBlur',
  });

  const onSubmit = (data) => {
    console.log("Submitted Data:", data);
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        {/* Username field (Yup validation works fine) */}
        <InputField name="username" label="Username" />
        
        {/* Password field (Yup validation works, but rules are ignored) */}
        <InputField
          name="password"
          label="Password"
          rules={{
            validate: (value) => value === 'test123' || 'Password must be test123',
          }}
        />

        <Button type="submit">Submit</Button>
      </form>
    </FormProvider>
  );
};

export default MyForm;

What I’ve Tried:

  1. Used validate inside rules for the password field.
  2. Tried different modes for useForm like onBlur and onChange.
  3. Removed Yup validation temporarily to confirm that rules validation works on its own (it does).

Expected Behavior:

I want to validate the password field using both the Yup schema (minimum length and required) and my custom validation logic in rules (e.g., matching the password to a specific value).


Solution

  • You can't combine Yup validation with rules; that's impossible.

    Describe in detail at this link.

    Instead, you can use Yup to handle that.

    password: yup
    .string()
    .required('Password is required')
    .test('is-valid', "Password must be test123", value => value === 'test123'),