React hook form error: "Function components cannot be given refs"
Answered
Cimarrón Uruguayo posted this in #help-forum
Cimarrón UruguayoOP
Hi, I have the following form component that uses react-hook-form. When I use the
Could someone guide me to understand why I'm getting this error and how I could fix it?
register function in my TextInput component, I get the error: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
import { useId } from 'react'
import { useForm} from 'react-hook-form'
export default function ContactForm() {
const form = useForm<ContactFormData>({
defaultValues: {
email: '',
...(((state?.success === false) && state.fields) ?? {})
},
resolver: zodResolver(contactSchema)
})
const {
register,
handleSubmit,
setError,
watch,
reset,
getFieldState,
formState: { errors }
} = form
return (
<form
ref={formRef}
onSubmit={handleSubmit(() => formAction(new FormData(formRef.current!)))}
>
<h2 className="font-display text-base font-semibold text-neutral-950">
Work inquiries
</h2>
<div className="isolate mt-6 -space-y-px rounded-2xl bg-white/50">
<TextInput
{...register('name')}
label="Name"
name="name"
autoComplete="name"
/>
</div>
</form>
)
}
function TextInput({
label,
...props
}: React.ComponentPropsWithRef<'input'> & { label: string }) {
let id = useId()
return (
<div className="group relative z-0 transition-all focus-within:z-10">
<input
type="text"
id={id}
{...props}
placeholder=" "
/>
<label
htmlFor={id}
>
{label}
</label>
</div>
)
}Could someone guide me to understand why I'm getting this error and how I could fix it?
Answered by joulev
it is a compromise from the old relic of class components where
ref isn't even considered a proper prop. to ensure backward compat or whatever, they decided to go ahead with this forwardRef compromise. finally it is gonna be gone soon. i hate this forwardRef so much13 Replies
Cimarrón UruguayoOP
The error goes away when i comment out the
register call on the TextInput component, but that basically means I can't connect the component to react-hook-form@Cimarrón Uruguayo Hi, I have the following form component that uses react-hook-form. When I use the `register` function in my `TextInput` component, I get the error:
> Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
tsx
import { useId } from 'react'
import { useForm} from 'react-hook-form'
export default function ContactForm() {
const form = useForm<ContactFormData>({
defaultValues: {
email: '',
...(((state?.success === false) && state.fields) ?? {})
},
resolver: zodResolver(contactSchema)
})
const {
register,
handleSubmit,
setError,
watch,
reset,
getFieldState,
formState: { errors }
} = form
return (
<form
ref={formRef}
onSubmit={handleSubmit(() => formAction(new FormData(formRef.current!)))}
>
<h2 className="font-display text-base font-semibold text-neutral-950">
Work inquiries
</h2>
<div className="isolate mt-6 -space-y-px rounded-2xl bg-white/50">
<TextInput
{...register('name')}
label="Name"
name="name"
autoComplete="name"
/>
</div>
</form>
)
}
function TextInput({
label,
...props
}: React.ComponentPropsWithRef<'input'> & { label: string }) {
let id = useId()
return (
<div className="group relative z-0 transition-all focus-within:z-10">
<input
type="text"
id={id}
{...props}
placeholder=" "
/>
<label
htmlFor={id}
>
{label}
</label>
</div>
)
}
Could someone guide me to understand why I'm getting this error and how I could fix it?
Wrap your TextInput in a forwardRef: https://react.dev/reference/react/forwardRef
@joulev Wrap your TextInput in a forwardRef: <https://react.dev/reference/react/forwardRef>
Cimarrón UruguayoOP
but what does this mean
what is the error actually trying to tell me
I'm not able to get past the ref jargon
@Cimarrón Uruguayo but what does this mean
register('name') has a ref. you cannot pass ref to custom components such as TextInput without wrapping it in forwardRef. this restriction will be lifted in react 19.import { forwardRef } from 'react';
const TextInput = forwardRef<
HTMLInputElement,
React.ComponentPropsWithoutRef<'input'> & { label: string }
>(function TextInput({ label, ...props }, ref) {
let id = useId()
return (
<div className="group relative z-0 transition-all focus-within:z-10">
<input
ref={ref}
type="text"
id={id}
{...props}
placeholder=" "
/>
<label
htmlFor={id}
>
{label}
</label>
</div>
)
})Cimarrón UruguayoOP
before it'd be passed via props
@Cimarrón Uruguayo before it'd be passed via props
it has never been passable via props.
for
ref and key are special react "props" that cannot be passed via conventional props in functional components.for
ref, it will become passable via props starting react 19, but in react 18 and before, you still need forwardRef.Cimarrón UruguayoOP
qh ok, I'm quite out of the loop with all this react stuff
thank you for the explanations:)
so from what I can gather, this forwardRef is a design choice by the react team
it is a compromise from the old relic of class components where
ref isn't even considered a proper prop. to ensure backward compat or whatever, they decided to go ahead with this forwardRef compromise. finally it is gonna be gone soon. i hate this forwardRef so muchAnswer