개인프로젝트 중, 임의로 포커싱을 주는 작업이 필요했다.
⇒ 댓글 아이콘을 클릭하면 아래 댓글 폼이 포커싱 되도록
작업은 간단했는데, useForm 의 setFocus
를 사용하면 될 일이었다. 하지만 어째서인지 포커싱이 되지 않았고, useRef 까지 사용했는데도 포커싱이 되지 않았는데..
'use client'
import { useController } from 'react-hook-form'
import style from './input.module.scss'
function Input({
control,
name,
rules,
required = false,
type = 'text',
label = '',
maxLength = 0,
placeholder = '',
onChange = () => {},
onBlur = () => {},
onFocus = () => {},
disabled,
...rest
}) {
const {
field,
fieldState: { error }
} = useController({
name,
control,
rules,
})
return (
<div className={style.field}>
<div
className={`${type === 'checkbox' ? 'checkbox' : ''} ${style.inputForm}`}
>
{label && <label htmlFor={name}>{label}</label>}
<input
id={name}
type={type}
className="input"
name={name}
value={field.value}
onChange={field.onChange}
onBlur={() => {
onBlur()
field.onBlur()
}}
onFocus={onFocus}
placeholder={placeholder}
disabled={disabled}
{...rest}
/>
{error && (
<span className={style.error}>
<em>*</em>
{error.message}
</span>
)}
</div>
</div>
)
}
export default Input
공식문서의 setFocus
예시를 그대로 사용했을 때는 정상작동하였다.
'use client'
import React from 'react'
import {useForm} from "react-hook-form";
function MessagePage() {
type FormValues = {
firstName: string;
};
let renderCount = 0;
const { register, handleSubmit, setFocus, watch } = useForm();
const onSubmit = (data: FormValues) => console.log(data);
renderCount++;
React.useEffect(() => {
setFocus("firstName");
console.log(watch("firstName"))
}, [setFocus]);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register("firstName")} placeholder="First Name" />
<button type="submit" onClick={() => {setFocus("firstName")}}>wpcnf</button>
</form>
);
}
export default MessagePage
setFocus
자체의 기능엔 문제가 없는 것을 확인했고, 나는 Input 을 공통 컴포넌트로 사용하고자 useController 로 사용했는데 이 부분에서 문제가 생기지 않았을까 추측했다.
그리고 공식문서에서 그 이유를 찾았는데, useController 의 field.ref
를 사용하지 않아 포커싱이 되지 않았던것을 알 수 있었다…
에러뿐만이 아닌 임의로 그냥 포커싱을 줄때도 field.ref
를 넣어주어야 한다는 사실을 알게됐다는😭
예시는 @material-ui/core 라는 UI 라이브러리를 사용해 TextField 의 inputRef 라는 속성에 들어있는데, 그냥 input 에는 ref 안에 field.ref
를 넣어주면 된다.
<input
id={name}
type={type}
className="input"
name={name}
value={field.value}
onChange={field.onChange}
ref={field.ref}
...
/>
테스트용으로 회원가입 하는 폼에 초기 포커싱으로 적용시켜봤는데, 정상 작동되는 것을 확인했다!
useEffect(() => {
setFocus("user")
}, [setFocus])
...
<Input
name="user"
control={control}
label="아이디"
maxLength="30"
type="text"
placeholder="아이디(5자 이상)"
/>