Typescript에서 useRef 사용하기 (With React)

Posted by , January 14, 2023
ReactJSTypescript
Series ofReactJS

thumbnail

노마드코더에서 몇 가지 학습을 하다가...

요새 기본기 부족을 느껴서 다시 React의 기본부터 한번 쭉 훝기로 하였다.
그러던 중 노마드코더 강의에서 hook 쪽을 듣는데 여기는 다 JS로 코드가 구성되어 있었다.

Typescript로 진행하는 나로써는 이 부분을 각 타입에 맞게끔 처리하면서 진행을 했다.
그 중 useRef 부분에서 약간 문제가 있어서 이 부분을 조사하며 알아간 내용을 정리하려 한다.


UseRef를 그래서?

음 여기 포스팅에서 UseRef를 직접적으로 다루진 않겠다.
이 부분은 따로 포스팅을 하고, 이번엔 어떤 식으로 쓰는지 알아보도록 한다.

먼저 타입을 정의 하기 전 useRef의 용도에 맞게 타입을 정의해준다.
아래 두 가지 형식을 확인하자.

값(Value)

제너릭과 초기값을 정해줘야 한다.

const name = useRef<string>("")
const age = useRef<number>(0)

DOM 객체

제너릭은 참조하는 HTML 타입을 넣어주고, 초기값은 null을 넣어준다.
왜 null을 넣어야 하면, useRef로 얻는 DOM은 처음으로 마운트 되기 전까진 null이다.

const input4Name = useRef<HtmlInputElement>(null)

만약 null로 초기 값을 설정하지 않는 경우 아래와 같은 에러가 발생하게 된다.

img01


내용이 이렇게 되어 있는데..(혹시 긁기 필요하신 분이 있을까봐 텍스트 버전)

'MutableRefObject<HTMLInputElement | undefined>' 형식은 'LegacyRef<HTMLInputElement> | undefined' 형식에 할당할 수 없습니다.
'MutableRefObject<HTMLInputElement | undefined>' 형식은 'RefObject<HTMLInputElement>' 형식에 할당할 수 없습니다.
'current' 속성의 형식이 호환되지 않습니다.
'HTMLInputElement | undefined' 형식은 'HTMLInputElement | null' 형식에 할당할 수 없습니다.
'undefined' 형식은 'HTMLInputElement | null' 형식에 할당할 수 없습니다.ts(2322)

근데 저렇게 에러가 나는 이유는 MutableRefObject의 제너릭을 보면 HTMLInputElement | undefined으로 되어 있다.
useRef의 전달인자를 확인해보면 아래와 같이 되어 있다.(사실 이렇게 이야기 하는것도 너무 오바지만...)

/**
 * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument
 * (`initialValue`). The returned object will persist for the full lifetime of the component.
 *
 * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
 * value around similar to how you’d use instance fields in classes.
 *
 * @version 16.8.0
 * @see https://reactjs.org/docs/hooks-reference.html#useref
 */
function useRef<T>(initialValue: T): MutableRefObject<T>
// convenience overload for refs given as a ref prop as they typically start with a null value
/**
 * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument
 * (`initialValue`). The returned object will persist for the full lifetime of the component.
 *
 * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
 * value around similar to how you’d use instance fields in classes.
 *
 * Usage note: if you need the result of useRef to be directly mutable, include `| null` in the type
 * of the generic argument.
 *
 * @version 16.8.0
 * @see https://reactjs.org/docs/hooks-reference.html#useref
 */
function useRef<T>(initialValue: T | null): RefObject<T>
// convenience overload for potentially undefined initialValue / call with 0 arguments
// has a default to stop it from defaulting to {} instead
/**
 * `useRef` returns a mutable ref object whose `.current` property is initialized to the passed argument
 * (`initialValue`). The returned object will persist for the full lifetime of the component.
 *
 * Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
 * value around similar to how you’d use instance fields in classes.
 *
 * @version 16.8.0
 * @see https://reactjs.org/docs/hooks-reference.html#useref
 */
function useRef<T = undefined>(): MutableRefObject<T | undefined>

전달인자를 제공해야 하기에 그렇다 -_-;;
근데 여기서 주목해야 하는 부분은 저 useRef의 반환이 두 가지 형태이다.

여기서 더 깊게 나가면 useRef라는 것에 대해 깊게 봐야 하는데,
이해 대해 useRef 포스팅 에서 다루고 있다.


뭔가 너무 간단한거 같은데?

물론 그렇다...
단순하게 제너릭에 타입만 정의하면 되는 것이기 때문에...

근데 이것도 위에서 언급한 useRef 포스팅 여기를 참조하면 이 부분에 대해 이해가 더 잘 될것이다.
무튼 이번 포스팅을 정리하면서 또 한번 배우게 되었다.