먼저 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>
이후 input
의 onKeyDown
과 onKeyUp
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이 되지 않는 것을 확인할 수 있었다. onSumbit
에 input value
를 추가한 새로운 url로 routing하는 코드가 구현되어 있었지만 이가 제대로 일어나지 않았다.
useRef
와 useForm
을 따로따로 사용하였을 때는 정상적으로 작동하는 것을 확인하였었기 때문에 두개를 같이 사용하기 때문에 발생한 문제임을 파악하고 원인을 찾았더니 의외로 금방 찾을 수 있었다.
원인은 바로 useForm
의 register
에 이미 ref
속성이 정의되어 있는 것이였다.
React-Hook-Form의 공식문서에 나와있드시 register
의 props는 { onChange, onBlur, name, ref }
이 있다.
이제 ref
속성을 뺀 나머지 register
를 input
속성에 추가하고 ref
는 inputRef
로 설정해 주면 문제가 해결된다.
하지만 하는 방법을 몰라 엄청 해매고있을 때 공식문서에서 방법을 찾을 수 있었다.
// 공식문서에서 제시하는 방법
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>
)
}
register
를 ref
와 rest
로 나누고
ref={(e) => {
ref(e)
firstNameRef.current = e // you can still assign to ref
}}
를 이용하여 useRef
와 register
의 ref
를 연결하여 input
의 ref
에 선언해주는 것 이다.
당장 내 코드에도 같은 방법으로 적용해 보았다.
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도 제대로 일어나는 것을 확인할수 있었다.