[React] useController 환경에서 setFocus 가 안되는 현상

hyejinJo·2024년 5월 16일
0

React

목록 보기
10/10
post-thumbnail

개인프로젝트 중, 임의로 포커싱을 주는 작업이 필요했다.

⇒ 댓글 아이콘을 클릭하면 아래 댓글 폼이 포커싱 되도록

작업은 간단했는데, 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자 이상)"
	/>

profile
UI Development 💡

0개의 댓글