useRef 올바르게 사용하기
💡 useRef란?
우리는 바닐라 자바스크립트에서
querySelector
,getElementById
등을 이용해DOM
을 직접적으로 선택하여 활용하곤 했었다.
하지만 리액트에서는 직접 DOM
에 접근하여 조작하는 것을 권장하지 않기에 우리는 Ref
를 활용해야 한다.
즉, 우리는 useRef
라는 내장 hooks를 통해 DOM
에 접근할 수 있고, 이를 리액트 컴포넌트 내에서 활용할 수 있는 것이다!
하지만 useRef
는 단순히 DOM
에 접근하기 위해서만 사용되는 것은 아니다. 데이터를 담는 저장소로써의 역할도 하는데, 데이터 저장소로써의 역할에 대해 먼저 이해한 뒤 DOM
접근 용도에 대해서 알아보도록 하자.
우선 간단하게 useRef
의 개괄적인 코드 형태부터 알아보자.
1 | import { useRef } from 'react'; |
이게 가장 기본적인 useRef
의 코드 구조다. 하지만 useRef
를 처음 접해보는 사람들은 중간에 쓰인 current
가 도대체 뭔지 의문부터 들었을 것이라 생각된다.
ref.current
?
current
는 쉽게 말해 데이터를 담는 상자(오브젝트)라고 볼 수 있다.
즉, 위에서 말했듯이ref
가 꼭DOM
에만 접근하기 위한 것은 아니라는 뜻이다.
ref.current
는 참조값에 접근하여 업데이트된 새로운 값을 current
에 담는다. 위의 코드 예시를 예로 들자면, div
라는 참조값에 뭔가 변화가 생기면 (물론 div
가 변할 일이 뭐가 있겠냐만은…) 우리의 ref.current
는 이를 감지하고 새로운 값을 담아내어 업데이트 하는 것이다.
조금 더 쉽고 직관적인 방식으로 예를 들어보면,
1 | import { useRef } from 'react'; |
근데… 그럼 이게 state
와 다른 점이 뭘까? 아래에서 더 자세히 알아보도록 하자.
🔮 useRef의 특징 (중요)
아래의 두 룰은 반드시 숙지해야 하는
useRef
의 핵심 개념이다.
- 참조값이 변해도 리렌더링을 야기하지 않는다.
- 컴포넌트가 리렌더링 되더라도 참조값은 유실되지 않는다.
글만 봐서는 감이 잡히지 않을 수도 있는데, 위에서 활용했던 Count 컴포넌트의 예시를 활용해 더 자세히 설명해보도록 하겠다.
1 | import { useRef } from 'react'; |
위의 코드에서 만약 count 횟수를 담는데 state
를 사용하고, setState()
를 통해 count값을 업데이트 해줬다면 어땠을까?
state
의 변화는 컴포넌트의 리렌더링을 야기하기 때문에 count 횟수가 변동될 때마다 컴포넌트가 리렌더링 되었을 것이다. 하지만 위의 useRef
의 예시에서는 count 횟수가 증가해도 컴포넌트가 리렌더링 되지 않는 것을 확인할 수 있다.
🎲 DOM에 접근하기
이제
DOM
에 접근하기 위한 용도로써의useRef
에 대해 알아보도록 하자.
useRef
를 통해 특정 DOM
에 접근하여 참조하는 것은 아래의 코드 방식을 따른다.
1 | import { useRef, useEffect } from 'react'; |
위의 코드를 글로써 다시 정리하자면…
- 우선,
const something = useRef();
와 같이 참조값을 정의하고 - 그 참조값을 DOM에 담아준다.
<div ref={something}> </div>
- 그리고 컴포넌트가 마운트 되면 우리의
something
이라는ref
는div
DOM
을 가리키게 된다.
타입스크립트에서의 방법 (추가)
TODO 앱을 만들다가
input
의 자동 포커싱 기능을 구현하려 했는데, 타입스크립트에서의useRef
방식에는 몇 가지 룰이 존재했다… 따라서 이를 추가적으로 기록해보고자 한다.
내가 간과했던 것은 초기 렌더링 시에는 참조값이 null
이기에, useEffect
내에서 current
가 비어있는지 여부를 우선적으로 체크해줘야 했는데 이를 빼먹었다. 아래의 코드를 봐보자!
1 | import { useRef, useEffect } from 'react'; |
마무리
여기까지가
useRef
의 기본 중의 기본이다.
참고로 첨언하자면, 참조값을 변화시키고 싶을 때는 함수형 컴포넌트 내에서 바로 변화를 주는 것이 아니라,useEffect
나 핸들링 함수 내에서 변화를 주는 것이 좋은 방식이라고 한다!
아직은 너무 기본적인 것들 뿐이고 부족한 것이 많지만… 기본적인 hooks들에 대한 공부를 우선적으로 마치고, 더 깊은 개념들과 활용법들에 대해 공부해볼 계획이다.
포스팅에 참조한 자료
The Complete Guide to useRef() and Refs in React
useRef 올바르게 사용하기