Zod form email required

I have a simple form, for my email auth using next-auth, right now if I enter my email and submit the form I get this error in my browser's console log:
{email: {…}}
email
:
{message: 'Required', type: 'invalid_type', ref: undefined}
[[Prototype]]
:
Object
{email: {…}}
email
:
{message: 'Required', type: 'invalid_type', ref: undefined}
[[Prototype]]
:
Object
This is how my Login Form component looks like:
import { emailSignUpSchema, SignUp } from '@/lib/zod/auth-schema'
import { zodResolver } from '@hookform/resolvers/zod'
import { signIn } from 'next-auth/react'
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'
import { z } from 'zod'
import Button from '../ui/button'
import Input from '../ui/input'
import Label from '../ui/label'

export default function LoginForm() {
const methods = useForm()
const { handleSubmit, register } = useForm<SignUp>({
resolver: zodResolver(emailSignUpSchema),
})

const onSubmit = async (data: SignUp) => {
console.log('loginWithEmail', data)
await signIn('email', {
email: data.email,
callbackUrl: '/dashboard',
})
}

const onErrors = (errors: any) => console.error(errors)

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit, onErrors)}>
<div className="space-y-6">
<Label htmlFor="email">Email address</Label>
<div className="mt-1">
<Input
id="email"
name="email"
type="email"
autoComplete="email"
required
/>
</div>
<Button
type="submit"
className="flex w-full justify-center"
color="primary"
>
Sign in
</Button>
</div>
</form>
</FormProvider>
)
}
import { emailSignUpSchema, SignUp } from '@/lib/zod/auth-schema'
import { zodResolver } from '@hookform/resolvers/zod'
import { signIn } from 'next-auth/react'
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'
import { z } from 'zod'
import Button from '../ui/button'
import Input from '../ui/input'
import Label from '../ui/label'

export default function LoginForm() {
const methods = useForm()
const { handleSubmit, register } = useForm<SignUp>({
resolver: zodResolver(emailSignUpSchema),
})

const onSubmit = async (data: SignUp) => {
console.log('loginWithEmail', data)
await signIn('email', {
email: data.email,
callbackUrl: '/dashboard',
})
}

const onErrors = (errors: any) => console.error(errors)

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit, onErrors)}>
<div className="space-y-6">
<Label htmlFor="email">Email address</Label>
<div className="mt-1">
<Input
id="email"
name="email"
type="email"
autoComplete="email"
required
/>
</div>
<Button
type="submit"
className="flex w-full justify-center"
color="primary"
>
Sign in
</Button>
</div>
</form>
</FormProvider>
)
}
7 Replies
utdev
utdevOP2y ago
The emailSignUpSchema looks like this
export const emailSignUpSchema = z.object({
email: z.string().email(),
})
export const emailSignUpSchema = z.object({
email: z.string().email(),
})
Neto
Neto2y ago
Are you registering the input for react hook form? {...(register ('email')} On the input
utdev
utdevOP2y ago
yeah this is the custom input component
import classNames from '@/utils/classNames'
import { useFormContext } from 'react-hook-form'
import React from 'react'

export interface InputProps extends React.ComponentPropsWithoutRef<'input'> {
name: string
className?: string
register: ReturnType<typeof useFormContext>['register']
}

export default React.forwardRef((props: InputProps, ref) => {
const { className, name, register, ...rest } = props
const { type } = { ...rest }

if (type === 'number') {
return (
<input
{...register(name, {
setValueAs: (v) => (v === '' ? undefined : parseInt(v, 10)),
})}
{...rest}
ref={ref as React.LegacyRef<HTMLInputElement>}
className={classNames(
'block w-full rounded-md border-slate-300 text-gray-600 focus:border-slate-500 focus:ring-1 focus:ring-slate-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:focus:border-slate-500 dark:focus:ring-slate-500 sm:text-sm',
className ?? ''
)}
/>
)
}

return (
<input
{...rest}
{...register(name)}
ref={ref as React.LegacyRef<HTMLInputElement>}
className={classNames(
'block w-full rounded-md border-slate-300 text-gray-600 focus:border-slate-500 focus:ring-1 focus:ring-slate-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:focus:border-slate-500 dark:focus:ring-slate-500 sm:text-sm',
className ?? ''
)}
/>
)
})
import classNames from '@/utils/classNames'
import { useFormContext } from 'react-hook-form'
import React from 'react'

export interface InputProps extends React.ComponentPropsWithoutRef<'input'> {
name: string
className?: string
register: ReturnType<typeof useFormContext>['register']
}

export default React.forwardRef((props: InputProps, ref) => {
const { className, name, register, ...rest } = props
const { type } = { ...rest }

if (type === 'number') {
return (
<input
{...register(name, {
setValueAs: (v) => (v === '' ? undefined : parseInt(v, 10)),
})}
{...rest}
ref={ref as React.LegacyRef<HTMLInputElement>}
className={classNames(
'block w-full rounded-md border-slate-300 text-gray-600 focus:border-slate-500 focus:ring-1 focus:ring-slate-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:focus:border-slate-500 dark:focus:ring-slate-500 sm:text-sm',
className ?? ''
)}
/>
)
}

return (
<input
{...rest}
{...register(name)}
ref={ref as React.LegacyRef<HTMLInputElement>}
className={classNames(
'block w-full rounded-md border-slate-300 text-gray-600 focus:border-slate-500 focus:ring-1 focus:ring-slate-500 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:focus:border-slate-500 dark:focus:ring-slate-500 sm:text-sm',
className ?? ''
)}
/>
)
})
And now I am calling it like this:
export default function LoginForm() {
const methods = useForm()
const inputRef = useRef<HTMLInputElement>(null)
const { handleSubmit, register } = useForm<SignUp>({
resolver: zodResolver(emailSignUpSchema),
})

const onSubmit = async (data: SignUp) => {
console.log('loginWithEmail', data)
await signIn('email', {
email: data.email,
callbackUrl: '/dashboard',
})
}

const onErrors = (errors: any) => console.error(errors)

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit, onErrors)}>
<div className="space-y-6">
<Label htmlFor="email">Email address</Label>
<div className="mt-1">
<Input
ref={inputRef}
register={methods.register}
id="email"
name="email"
type="email"
autoComplete="email"
required
/>
</div>
export default function LoginForm() {
const methods = useForm()
const inputRef = useRef<HTMLInputElement>(null)
const { handleSubmit, register } = useForm<SignUp>({
resolver: zodResolver(emailSignUpSchema),
})

const onSubmit = async (data: SignUp) => {
console.log('loginWithEmail', data)
await signIn('email', {
email: data.email,
callbackUrl: '/dashboard',
})
}

const onErrors = (errors: any) => console.error(errors)

return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit, onErrors)}>
<div className="space-y-6">
<Label htmlFor="email">Email address</Label>
<div className="mt-1">
<Input
ref={inputRef}
register={methods.register}
id="email"
name="email"
type="email"
autoComplete="email"
required
/>
</div>
@Neto I am probably missing something small
Neto
Neto2y ago
Do you need to pass the register into the inner component? Using the register on the Input component isn't better?
utdev
utdevOP2y ago
Not sure If i use the simple <input tag with the email name it works, so there is something wrong with my Input component I think Just don't see what I may be missing 🤔 Not sure if I do this
<Input
{...register('email')}
name="email"
type="email"
autoComplete="email"
required
/>
<Input
{...register('email')}
name="email"
type="email"
autoComplete="email"
required
/>
It works but the Input component should do the register login inside using the name 😕
Unknown User
Unknown User2y ago
Message Not Public
Sign In & Join Server To View
utdev
utdevOP2y ago
Just saw that you replied, I am going to try that later, thanks, yeah I got confused with the different methods I think.
Want results from more Discord servers?
Add your server