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:
This is how my Login Form component looks like:
{email: {…}}
email
:
{message: 'Required', type: 'invalid_type', ref: undefined}
[[Prototype]]
:
Object
{email: {…}}
email
:
{message: 'Required', type: 'invalid_type', ref: undefined}
[[Prototype]]
:
Object
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
The
emailSignUpSchema
looks like this
export const emailSignUpSchema = z.object({
email: z.string().email(),
})
export const emailSignUpSchema = z.object({
email: z.string().email(),
})
Are you registering the input for react hook form?
{...(register ('email')}
On the inputyeah this is the custom input component
And now I am calling it like this:
@Neto I am probably missing something small
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 ?? ''
)}
/>
)
})
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>
Do you need to pass the register into the inner component?
Using the register on the Input component isn't better?
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
It works but the Input component should do the register login inside using the name 😕
<Input
{...register('email')}
name="email"
type="email"
autoComplete="email"
required
/>
<Input
{...register('email')}
name="email"
type="email"
autoComplete="email"
required
/>
Unknown User•2y ago
Message Not Public
Sign In & Join Server To View
Just saw that you replied, I am going to try that later, thanks, yeah I got confused with the different methods I think.