[React] useForm 과 useRef Hook을 함께 사용하여 동적으로 길어지는 Input 구현하기

woodylovesboota·2023년 9월 17일
0
post-thumbnail

길어지는 input 만들기

먼저 React의 useForm hook을 사용하여 input을 만들었다.

const { register, handleSubmit } = useForm<IForm>();

const onValid = (data: IForm) => {
  ...
};

...

<Form onSubmit={handleSubmit(onValid)}>
  <Input {...register("destination", {required:true})} />
</Form>

onSubmit이나 onValid는 중요한 부분이 아니니 생략하고 입력에 따라 input 길이를 조절해야 하기 때문에 useRef hook을 이용하여 input의 속성을 수정하였다.

const inputRef = useRef<HTMLInputElement | null>(null);

...

<Form onSubmit={handleSubmit(onValid)}>
  <Input 
    {...register("destination", {required:true})}
    ref={inputRef}
    />
</Form>

이후 inputonKeyDownonKeyUp eventListener를 이용하여 input의 길이를 조절하였다.

const handleWidth = () => {
  inputRef &&
    inputRef.current &&
    (inputRef.current.style.width = `${inputRef.current?.value.length * 60 + 150}px`);
};

...

<Input
  {...register("destination", {required:true})}
  ref={inputRef}
  onKeyDown={handleWidth}
  onKeyUp={handleWidth}
  />

문제

구현을 마치고 테스트 해보니 input의 길이는 정상적으로 늘어나지만 submit이 되지 않는 것을 확인할 수 있었다. onSumbitinput value를 추가한 새로운 url로 routing하는 코드가 구현되어 있었지만 이가 제대로 일어나지 않았다.

문제해결

useRefuseForm을 따로따로 사용하였을 때는 정상적으로 작동하는 것을 확인하였었기 때문에 두개를 같이 사용하기 때문에 발생한 문제임을 파악하고 원인을 찾았더니 의외로 금방 찾을 수 있었다.

원인은 바로 useFormregister에 이미 ref 속성이 정의되어 있는 것이였다.

React-Hook-Form의 공식문서에 나와있드시 register의 props는 { onChange, onBlur, name, ref }이 있다.

이제 ref 속성을 뺀 나머지 registerinput 속성에 추가하고 refinputRef로 설정해 주면 문제가 해결된다.

하지만 하는 방법을 몰라 엄청 해매고있을 때 공식문서에서 방법을 찾을 수 있었다.

// 공식문서에서 제시하는 방법
import React, { useRef } from "react"
import { useForm } from "react-hook-form"


type Inputs = {
  firstName: string
  lastName: string
}


export default function App() {
  const { register, handleSubmit } = useForm<Inputs>()
  const firstNameRef = useRef<HTMLInputElement | null>(null)
  const onSubmit = (data) => console.log(data)
  const { ref, ...rest } = register("firstName")


  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input
        {...rest}
        name="firstName"
        ref={(e) => {
          ref(e)
          firstNameRef.current = e // you can still assign to ref
        }}
      />


      <button>Submit</button>
    </form>
  )
}

registerrefrest로 나누고

ref={(e) => {
  ref(e)
  firstNameRef.current = e // you can still assign to ref
}}

를 이용하여 useRefregisterref를 연결하여 inputref에 선언해주는 것 이다.

당장 내 코드에도 같은 방법으로 적용해 보았다.

const { ref, ...rest } = register("destination");

<Form onSubmit={handleSubmit(onValid)}>
  <Input
    {...rest}
    name="destination"
    ref={(e) => {
      ref(e);
      inputRef.current = e;
    }}
    onKeyDown={handleWidth}
    onKeyUp={handleWidth}
    />
</Form>

이후 submit도 제대로 일어나는 것을 확인할수 있었다.

0개의 댓글

관련 채용 정보