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의 타입이 어떻게 정해지는지는 MutableRefObjectRefObject가 어떻게 정의되어 있는지를 봐야 할 것 같다.

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>;

에 해당한다. 그러므로 inputRefRefObject<T>타입이고, inputRef.currentT | null 타입이다. 그런데 이 예시에서 T는 무슨 타입일까? 우리가 취득하고자 하는 DOM element가 input이라면 HTMLInputElement, div라면 HTMLDivElement, button이라면 HTMLButtonElement 등이 된다. 따라서 타입을 명시해주고 싶다면

const inputRef = useRef<HTMLInputElement>(null) ... <input ref={inputRef}/>

처럼 사용하면 된다.

참고


React docs - useRef

React docs - Referencing Values with Refs

TypeScript React에서 useRef의 3가지 정의와 각각의 적절한 사용법

[React] TypeScript useRef 사용법 (+ ref 객체 타입)

타입스크립트 교과서(조현영 저)