0. 글을 쓰게 된 계기
최근 Test Code 관련 강의를 수강하던 중, 소스코드의 input 이 아래와 같이 구현 된 것을 발견했다.
const InputWithRef = () => {
const inputRef = useRef();
const addPost = (post) => {
// 글 추가하는 함수
}
const onSubmit = () => {
const { value } = inputRef.current;
addPost(value)
}
return(
<form>
<input type="text"
ref={inputRef}
onSubmit={onSubmit}
/>
</form>
)
}
코드 자체는 문제가 없는데, 무엇이 문제여서 글을 쓰게 됬을까?
1. 배운거랑 달라요!
정말 이 문제 때문이었다.
조금 더 자세히 말하자면 나는 input창을 useState를 이용하여 구현했는데,
해당 코드에서는 useRef를 이용하여 구현했다는 것.
원래 내가 구현하던 방식의 코드를 보자.
const TestInputWithState = () => {
const [input, setInput] = useState();
const addPost = (post) => {
// 글 추가하는 함수
}
const onSubmit = () => {
addPost(input)
}
return(
<form>
<input type="text"
onChange={(e) => setInput(e.target.value)}
onSubmit={onSubmit}
/>
</form>
)
}
원래는 이런식으로
1. state를 생성하여 input의 value로 지정해주고
2. onChange를 이용하여 state를 변경시켜주고
3. onSubmit 호출시 input state 값 그대로 이용
이라는 절차대로 코드를 구현했었다.
이렇게 구현한 이유는 단순하다.
React를 처음 배울때 input창을 이런 식으로 구현했었다.
그러나 최근에 input창에 value로 state를 주면 input 창의 값을 바꿀 때 마다 재랜더링 되는게
성능적으로 무리가 없을까? 하여 조금 신경쓰였는데,
위 처럼 useRef를 사용하여 구현할 수 있다면
재랜더링 이슈를 방지할 수 있어서 찾아보았다.
2. 권고사항: useState를 쓰세요
해당 문제를 알아보다가, 프론트엔드 커뮤니티에 질문해 본 결과,
제어 / 비제어 컴포넌트에 대해 알게되었다
관련 링크
https://ko.reactjs.org/docs/uncontrolled-components.html
비제어 컴포넌트 – React
A JavaScript library for building user interfaces
ko.reactjs.org
요약하자면
input 창의 값이 바뀌는 상황에 대해서 비제어 컴포넌트인 useRef를 사용하게 되면 몇몇 오류가 발생할 수 있기에
재랜더링 이슈가 있다 하더라도 제어 컴포넌트인 useState 형식으로 Input창을 구현하는걸 권고하고 있다.
3. ...그럼 무조건 useState를 사용해야 해?
사실 그건 아니라고 한다.
위 공식문서에서도 권고사항이고, 또 확실히 state는 재랜더링 이슈는 있기도 해서
useRef를 사용하여 Input창을 구현해도 되는 상황이 있다.
1. 비밀번호 일치여부 검사, 입력값 길이 검사 등 : input의 값이 바뀔 때 마다 특정 로직을 수행해야 할 때
이럴땐 묻고 따지지도 말고 state를 사용하자.
확실하게 value 값을 제어하고, 이를 통해 로직을 구현할 수 있기 때문에 재랜더링 이슈가 있더라도 state를 사용하는게 맞다.
2. 검색창 검색, 문서제출 등 : input값의 로직이 한번만 수행될 때
글을 쓰거나 네이버 검색창 같은, submit 하는 순간에서만 로직이 일어날 때는 비제어 컴포넌트인 useRef를 사용해도 된다고 한다. 앞서 예제코드 같은 상황 말이다.
결국, 특정 상황에서 권고사항을 따르느냐, 성능에 좀 더 집중을 하느냐를 적절히 판단해서 구현해야 하는 것인데,
정말 리액트는 배울수록 어려운 것 같다.
추가로, 재랜더링 이슈는 throttle 이나 debounce 라는 걸로 단점을 보완 할 수 있다고 한다.
나중에 좀 더 찾아봐야겠다.
틀린 문제의 지적사항은 언제나 환영입니다 :)
'Front End' 카테고리의 다른 글
[React] 부모 요소의 Event 제어하기 (0) | 2022.05.31 |
---|---|
[React] 리액트에서 멋지게 클래스 사용하기 (0) | 2022.05.28 |
React + Type Script 로 팝업창 만들기( + Type {children: Element} has no properties )에러 해결방법 (0) | 2022.05.18 |
[TypeScript] 객체 속 객체(?)의 타입을 정의하는 방법 (0) | 2022.05.12 |
⚛️React hooks + MobX 사용해보기 (1) (0) | 2022.04.03 |