보통 useState
를 사용해서 input
을 상대하면, 계속 그 컴포넌트가 쓸때없이 랜더링되는 현상이 발생한다.
그래서 해당 input
의 값만 useRef
를 통해서 string
으로 받아낸다.
여기서 가장 중요한 것은 useRef
를 사용한 것이 그냥 string
값일 뿐이지 그 input
을 참조하는 것은 아니라는 것이다.
그래서 다음과 같은 로직이 나올 수 있다.
const TodoInput: React.FC = (): JSX.Element => {
const todoVal = useRef<string>('')
const todoInputRef = useRef<HTMLInputElement>(null)
// 작성하기
const postClickHandler = (): void => {
if (!todoVal.current || todoInputRef.current === null) {
alert('할 일을 적어주세요.');
todoInputRef.current?.focus();
return;
}
// input값과 id를 저장
const newData: T_todo = {
id: Date.now(),
todo: todoVal.current,
};
dispatch(postTodo(newData));
todoVal.current = '';
todoInputRef.current.value = '';
};
return (
<StyledDiv>
<input
type="text"
ref={todoInputRef}
onChange={(e) => (todoVal.current = e.target.value)}
/>
<button onClick={postClickHandler}>작성하기</button>
</StyledDiv>
);
}
코드에서 todoVal
은 그저 string
으로 input
값을 참조하는 것이고 실제적으로 input
이 onChange
될 때마다 값이 업데이트는 되고 있지만[1], 컴포넌트가 랜더링되지는 않는다.
또, UX를 위해서 input
이 빈 칸일 때 사용자가 버튼을 누르면, 할 일을 적어주세요
라는 알림과 함께 해당 input
에 focus
를 주는 기능에서는 직접 todoInputRef
를 통해 input
을 참조하고[2], todoInputRef.current?.focus();
를 통해서 focus()
와 blur()
같은 메소드 사용이 가능하다.
이로써, 다음부터 input을 쓸 때는 불필요한 재랜더링을 막기위해서 useRef로 사용해봐야겠다.
[1]:
onChange={(e) => (todoVal.current = e.target.value)}
, 즉 input이 변경될 때 마다, todoVal의 current값은 e.target.value(input의 값)입니다. 라고 해주는 것이다.
[2]:
<input ref={todoInputRef}/>