How to use Yup and React Hook Form to Validate an Object with nested properties

616 Views Asked by At

My form submits to backend, but does not validate on the server-side.

Here is the schema and the object it is based on:

const createEmployeeSchema = yup.object().shape({
    name: yup.string().max(100).required(),
    social: yup.object().shape({
        facebook: yup.string().required(),
        instagram: yup.string().required(),
    })
})

type CreateEmployeeDTO = {
    name: string
    social: {
        facebook: string
        instagram: string
    }
}

Here is the CreateEmployee form:

export const CreateEmployee = () => {
    const createEmployeeQuery = useCreateEmployeeQuery()

    return (
        <Form<CreateEmployeeDTO, typeof createEmployeeSchema>
            id="create-employee"
            onSubmit={async (values) => {

                createEmployeeQuery.mutateAsync(values)
            }}
            schema={createEmployeeSchema}
        >
            {(methods) => (
                <>
                    <Typography fontWeight={600}>Employee Information</Typography>
                    <TextFieldMUI standard small name={'name'} label={'Name'} />
                    <TextFieldMUI standard small name={'social.facebook'} label={'Facebook'} />
                    <TextFieldMUI standard small name={'social.instagram'} label={'Instagram'} />
                    <Button>Submit</Button>
                </>
            )}
        </Form>
    )
}

Here is the wrapper <Form>:

import { yupResolver } from '@hookform/resolvers/yup';
import clsx from 'clsx';
import * as React from 'react';
import { FormProvider, SubmitHandler, UseFormProps, UseFormReturn, useForm } from 'react-hook-form';
import * as yup from 'yup';


type FormProps<TFormValues, Schema> = {
  className?: string;
  onSubmit: SubmitHandler<TFormValues>;
  children: (methods: UseFormReturn<TFormValues>) => React.ReactNode;
  options?: UseFormProps<TFormValues>;
  id?: string;
  schema?: Schema;
};

export const Form = <
  TFormValues extends Record<string, unknown> = Record<string, unknown>,
  Schema extends yup.ObjectSchema<yup.AnyObject> = yup.ObjectSchema<yup.AnyObject>
>({
  onSubmit,
  children,
  className,
  options,
  id,
  schema,
}: FormProps<TFormValues, Schema>) => {
  const methods = useForm<TFormValues>({ ...options, resolver: schema && yupResolver(schema) });
  return (
    <FormProvider {...methods} >
      <form
        className={clsx('space-y-6', className)}
        onSubmit={methods.handleSubmit(onSubmit)}
        id={id}
      >
        {children(methods)}
      </form>
    </FormProvider>
  );
};

'name' successfully validates. 'social.facebook' and 'social.instagram' do not validate.

I suspect this has to do with this portion of the <Form> component: Schema extends yup.ObjectSchema<yup.AnyObject> = yup.ObjectSchema<yup.AnyObject>

0

There are 0 best solutions below