vamo
TTCTheo's Typesafe Cult
•Created by vamo on 11/29/2023 in #questions
React hook form with zod submit error:
I found out what the issue was: the useForm from 2 different files holds a different instance, I fixed it and it works fine but idk if my implementation is that great, perhaps someone could tell me what I could improve in it or show me his/hers implementation for reacthookform + zod:
import { FieldErrors, FieldValues, UseFormRegister, FieldError, } from 'react-hook-form'
import React from 'react'
interface Inputs { name: string inputType: string register?: UseFormRegister<FieldValues>
errors?: FieldErrors<FieldValues> placeholder?: string className?: string
}
export default function HookFormInput(props: Inputs) {
return (
<div>
<input className={props.className} placeholder={props.placeholder}
type={props.inputType} {...props.register?.(props.name)}/>
{props.errors?.[props.name] && (
<span>{(props.errors[props.name] as FieldError)?.message}</span>
)}
</div>
)
}
Form wrapper:
import React, { ReactElement, ReactNode } from 'react'
import { DefaultValues, FieldValues, SubmitErrorHandler, useForm} from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { ZodType } from 'zod'
interface HookForm<T extends FieldValues> { children: ReactNode
onSubmit: (data: T) => void onError: SubmitErrorHandler<T> schema: ZodType<any, any, any>
defaultValues?: DefaultValues<T>}
export function HookFormComponent<T extends FieldValues>({ children, onSubmit, onError, schema, defaultValues, }: HookForm<T>) {
const { handleSubmit, register, formState: { errors }, } = useForm<T>({ defaultValues, resolver zodResolver(schema), })
const renderChildren = () => {
return React.Children.map(children as ReactElement, (child) => {
if (child.type === 'button') {
return React.cloneElement(child)
}
return React.cloneElement(child, {
register,
errors,
})
})
}
return (
<form onSubmit={handleSubmit(onSubmit, onError)}>{renderChildren()}</form>
)
}
import { FieldErrors, FieldValues, UseFormRegister, FieldError, } from 'react-hook-form'
import React from 'react'
interface Inputs { name: string inputType: string register?: UseFormRegister<FieldValues>
errors?: FieldErrors<FieldValues> placeholder?: string className?: string
}
export default function HookFormInput(props: Inputs) {
return (
<div>
<input className={props.className} placeholder={props.placeholder}
type={props.inputType} {...props.register?.(props.name)}/>
{props.errors?.[props.name] && (
<span>{(props.errors[props.name] as FieldError)?.message}</span>
)}
</div>
)
}
Form wrapper:
import React, { ReactElement, ReactNode } from 'react'
import { DefaultValues, FieldValues, SubmitErrorHandler, useForm} from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { ZodType } from 'zod'
interface HookForm<T extends FieldValues> { children: ReactNode
onSubmit: (data: T) => void onError: SubmitErrorHandler<T> schema: ZodType<any, any, any>
defaultValues?: DefaultValues<T>}
export function HookFormComponent<T extends FieldValues>({ children, onSubmit, onError, schema, defaultValues, }: HookForm<T>) {
const { handleSubmit, register, formState: { errors }, } = useForm<T>({ defaultValues, resolver zodResolver(schema), })
const renderChildren = () => {
return React.Children.map(children as ReactElement, (child) => {
if (child.type === 'button') {
return React.cloneElement(child)
}
return React.cloneElement(child, {
register,
errors,
})
})
}
return (
<form onSubmit={handleSubmit(onSubmit, onError)}>{renderChildren()}</form>
)
}
3 replies
TTCTheo's Typesafe Cult
•Created by vamo on 11/29/2023 in #questions
React hook form with zod submit error:
and thats how Im trying to use it:
import HookFormComponent from 'modules/common/components/Form/HookForm'
import HookFormInput from 'modules/common/components/Form/HookFormInput'
import { z } from 'zod'
const WeAreEverything = () => {
const contactSchema = z.object({
name: z.string(),
email: z.string().email('needs to be an email'),
})
type ContactSchema = z.infer<typeof contactSchema>
return (
<div>
<HookFormComponent<ContactSchema>
onError={(err) => {
console.error(err, ': Form error values')
}}
onSubmit={(data) => {
console.log(data, ': Form values')
}}
schema={contactSchema}
>
<HookFormInput name="name" type="text" />
<HookFormInput name="email" type="email" />
<button type="submit">submit</button>
</HookFormComponent>
</div>
)
}
export default WeAreEverything
import HookFormComponent from 'modules/common/components/Form/HookForm'
import HookFormInput from 'modules/common/components/Form/HookFormInput'
import { z } from 'zod'
const WeAreEverything = () => {
const contactSchema = z.object({
name: z.string(),
email: z.string().email('needs to be an email'),
})
type ContactSchema = z.infer<typeof contactSchema>
return (
<div>
<HookFormComponent<ContactSchema>
onError={(err) => {
console.error(err, ': Form error values')
}}
onSubmit={(data) => {
console.log(data, ': Form values')
}}
schema={contactSchema}
>
<HookFormInput name="name" type="text" />
<HookFormInput name="email" type="email" />
<button type="submit">submit</button>
</HookFormComponent>
</div>
)
}
export default WeAreEverything
3 replies