useRef를 타이핑하는 방법
TypeScript에서 useRef를 사용하기
Table Of Contents
들어가기
useState를 타이핑하는 방법을 저번주에 알아봤는데, useRef 또한 타이핑해야 하는 일이 생겨 알아보게 되었다.
useRef
란?
useRef
역시 React.js의 hook 중 하나로, 렌더링에 필요하지 않은 값을 참조할 수 있게 해준다.
const ref = useRef(initialValue);
처럼 사용하면 된다.
ref
는 컴포넌트에서 어떤 값을 저장하고는 싶지만, 다시 렌더링을 트리거하고 싶지 않을 때, 또는 DOM을 조작할 때 사용할 수 있다.
예시
먼저 렌더링에 영향을 주지 않는 값을 저장하기 위해서 useRef
를 사용해보자.
const count = useRef(0);
이렇게 하면 count
변수의 초기값은 0이 된다.
DOM을 조작하려면 아래처럼 사용한다.
const inputRef = useRef(null) ... <input ref={inputRef}/>
이 경우에, inputRef
는 최초 mount되기 전에는 null
이다.
# TypeScript 파일 살펴보기
function useRef<T>(initialValue: T): MutableRefObject<T>; function useRef<T>(initialValue: T | null): RefObject<T>; function useRef<T = undefined>(): MutableRefObject<T | undefined>;
세 가지의 오버로딩이 있다.
먼저, 3번째 오버로딩은 initialState를 초기 인자로 넘겨주지 않은 경우이다.
첫 번째와 두 번째 오버로딩은 (별도로 타이핑을 하지 않는 이상) 초기 인자로 null
이 주어지는지 아닌지의 차이로 정해진다.
최종적으로 ref의 타입이 어떻게 정해지는지는 MutableRefObject
와 RefObject
가 어떻게 정의되어 있는지를 봐야 할 것 같다.
interface MutableRefObject<T> { current: T; }
interface RefObject<T> { readonly current: T | null; }
RefObject
는 current가 readonly
인 점이 눈에 들어온다. 두 번째 오버로딩에서는 current의 값을 변경할 수 없을 것이다.
첫 번째 예시에서 count.current
값은 변경이 가능한데, 이는 인자로 0을 제공했기 때문에 첫 번째 오버로딩이 되어 current값이 변경 가능하기 때문이다.
두 번째 에시에서는 inputRef.current
의 값이 변경 불가능하다. 인자로 null을 제공해 두 번째 오버로딩이 되었기 때문이다.
실제 코드에서 살펴보기
1. 값 저장 용도
const count = useRef(0);
위에서 본 예시를 다시 가져왔다. 이 경우에는 null
이외의 인자를 제공했기 때문에 첫 번째
function useRef<T>(initialValue: T): MutableRefObject<T>;
오버로딩에 해당한다.
current값의 타입 = 인자의 타입이 되고, ref
자체의 타입은 MutableRefObject<타입>
이다.
예시에서는 0이 number로 추론될 것이기 때문에 count는 MutableRefObejct<number>
타입이다.
만약에 타입을 명시해 주고 싶다면
const count = useRef<number>(0);
처럼 써줄 수 있다.
당연히 number 외에 다른 값들도 넣을 수 있다. Coords라는 타입을 정의하고 해당 타입을 대입하는 것도 가능하다.
export interface Coords { x: number; y: number; } ... const coords = useRef<Coords>({ x: 0, y: 0 });
이 경우, coords의 타입은 MutableRefObject<Coords>
이다!
2. DOM 참조 용도
const inputRef = useRef(null) ... <input ref={inputRef}/>
input 태그를 가리키는 ref를 선언했다.
인자가 null
이기 때문에 두 번째 오버로딩
function useRef<T>(initialValue: T | null): RefObject<T>;
에 해당한다.
그러므로 inputRef
는 RefObject<T>
타입이고, inputRef.current
는 T | null
타입이다.
그런데 이 예시에서 T는 무슨 타입일까?
우리가 취득하고자 하는 DOM element가 input이라면 HTMLInputElement
, div라면 HTMLDivElement
, button이라면 HTMLButtonElement
등이 된다.
따라서 타입을 명시해주고 싶다면
const inputRef = useRef<HTMLInputElement>(null) ... <input ref={inputRef}/>
처럼 사용하면 된다.
참고
React docs - Referencing Values with Refs
TypeScript React에서 useRef의 3가지 정의와 각각의 적절한 사용법
[React] TypeScript useRef 사용법 (+ ref 객체 타입)
타입스크립트 교과서(조현영 저)