Reputation: 1189
How do you implement set focus in an input using React-Hook-Form, this is what their FAQ's "How to share ref usage" code here https://www.react-hook-form.com/faqs/#Howtosharerefusage
import React, { useRef } from "react";
import { useForm } from "react-hook-form";
export default function App() {
const { register, handleSubmit } = useForm();
const firstNameRef = useRef();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input name="firstName" ref={(e) => {
register(e)
firstNameRef.current = e // you can still assign to ref
}} />
<input name="lastName" ref={(e) => {
// register's first argument is ref, and second is validation rules
register(e, { required: true })
}} />
<button>Submit</button>
</form>
);
}
I tried set focusing the ref inside useEffect but it doesn't work:
useEffect(()=>{
firstNameRef.current.focus();
},[])
Neither does inside the input:
<input name="firstName" ref={(e) => {
register(e)
firstNameRef.current = e;
e.focus();
}} />
Upvotes: 28
Views: 55674
Reputation: 1
Maybe my solution will help anybody cuz I was struggling a lot...
...
const ContentForm = () => {
const [isPending, startTransition] = useTransition();
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
word: '',
},
});
const { handleSubmit, control, setFocus, resetField } = form;
useEffect(() => {
setFocus('word');
}, [isPending]);
...
in this case every time after submit you focus on the input (I have one)
Upvotes: 0
Reputation: 90
You can use useMergeRefs
from Chakra to combine the focus ref and the refs that react-hook-form uses, and pass that on to the input
component:
import {
Input,
FormControl,
FormLabel,
useMergeRefs
} from "@chakra-ui/react";
const focusRef = useRef(null);
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl isInvalid={Boolean(errors.newRlName)}>
<FormLabel>name</FormLabel>
<Input
type="text"
{...register("name")}
tabIndex={1}
ref={useMergeRefs(editRef, register("name").ref)}
/>
<FormErrorMessage>{errors.name && errors.name?.message}</FormErrorMessage>
</FormControl>
</form>
Upvotes: 0
Reputation: 200
const {
register,
handleSubmit,
setFocus, // here
formState: { errors },
} = useForm<FormFields>({
resolver: yupResolver(LoginSchema),
mode: "onTouched",
});
useEffect(() => {
setFocus("email");
}, [setFocus]);
Upvotes: 1
Reputation: 351
I can't comment (I don't have enough reputation), but without setting a timeout, setFocus
didn't work. After adding a simple timeout from Subham's answer, it worked like a charm!
PS: Even adding a timeout of 0: setTimeout(() => setFocus(fieldName), 0)
works. Can anyone explain?
Upvotes: 7
Reputation: 51
I think you can simply use ref={(el) => el.focus()}
to set the focus. The catch here is to make sure no other element within your page is also setting focus right after that el.focus()
call.
Upvotes: 0
Reputation: 1068
You can set the focus using the setFocus
helper returned by the useForm hook (no need to use a custom ref):
const allMethods = useForm();
const { setFocus } = allMethods;
...
setFocus('inputName');
https://react-hook-form.com/api/useform/setFocus
Upvotes: 21
Reputation: 905
If you using Version 7, you can check this link in the docs
https://www.react-hook-form.com/faqs/#Howtosharerefusage
Upvotes: 6
Reputation: 101
useEffect(() => {
if (firstNameRef.current) {
register(firstNameRef.current)
firstNameRef.current.focus()
}
}, []);
<input name="firstName" ref={firstNameRef} />
Got this from : https://github.com/react-hook-form/react-hook-form/issues/230
Upvotes: 3
Reputation: 624
Are you using Typescript?
If so, replace...
const firstNameRef = useRef();
With...
const firstNameRef = useRef<HTMLInputElement | null>(null);
Upvotes: 5