[TypeScirpt] Hook에 타입 지정하기

현용찬·2024년 9월 2일

한줄 요약

  1. useState에서는 기본적으로 초깃값으로 타입 추론이 잘 되지만 타입 추론을 잘 못할 때는 제너릭을 사용해서 타입을 지정해 줄 수 있다.
  2. useRef를 쓸 때는 대상이 되는 dom 노드를 제너릭으로 지정해 두고 초깃값이 없으면 타입 추론이 맞지 않기 때문에 보통 null 값을 넣어준다.

useState

보통 아래의 코드와 같이 useState는 타입을 잘 지정해주기 때문에 타입을 지정을 굳이 안해줘도 된다

  const [values, setValues] = useState({
    username: "",
    password: "",
  });

하지만 아래와 같이 빈배열을 초깃값을 쓰면 이런경우에는 타입을 추론할 수 없으니 state 타입이 never(절때로 있을 수 없는 값)이라는 타입의 배열이된다

const[name,setName]=useState<string[]>([])

따라서 다음과 같이 타입을 선언해 준다

  const [values, setValues] = useState<{ username: string; password: string }>({
    username: "",
    password: "",
  });

useRef

Ref로 HTML DOM 노드를 가져와서 쓸거라면 제네릭으로 HTML DOM 노드에 해당하는 타입을 적어 주면 된다. 또한 초깃값이 비어 있으면 추론된 Ref 객체 타입과 Ref를 사용하는 곳의 타입이 맞지 않기 때문에 초깃값으로 null을 지정해 주면 된다.

const formRef = useRef<HTMLFormElement>(null);

useRef에서는 제네릭으로 대상이 되는 노드의 타입을 정해 줄 수 있다.

예제

아래의 코드에 hook의 타입 적용하기

import { useEffect, useRef, useState } from 'react';

function App() {
  const [scores, setScores] = useState([]);
  const buttonRef = useRef();

  useEffect(() => {
    if(buttonRef.current) buttonRef.current.focus();
  }, []);

  function handleClick() {
    const num = Math.floor(Math.random() * 10);
    setScores([...scores, num]);
  }

  return (
    <div>
      <div>{scores}</div>
      <button onClick={handleClick} ref={buttonRef}>랜덤 숫자</button>
    </div>
  );
}

export default App;

정답

import { useEffect, useRef, useState } from 'react';

function App() {
  const [scores, setScores] = useState([]);
  const buttonRef = useRef();

  useEffect(() => {
    if(buttonRef.current) buttonRef.current.focus();
  }, []);

  function handleClick() {
    const num = Math.floor(Math.random() * 10);
    setScores([...scores, num]);
  }

  return (
    <div>
      <div>{scores}</div>
      <button onClick={handleClick} ref={buttonRef}>랜덤 숫자</button>
    </div>
  );
}

export default App;

코드 설명

useState<T>() 훅에서 초기값이 빈 배열([])이면 스테이트의 타입이 제대로 추론되지 않기 때문에 타입을 명시적으로 지정해 주어야 한다. 제네릭을 이용하면 스테이트의 타입을 명시적으로 지정할 수 있다. 숫자 배열 타입(number[] 타입)으로 지정해주려면 아래와 같이 쓰면된다.
const [scores, setScores] = useState<number[]>([]);

useRef<T>() 훅에서 제네릭으로 Ref의 대상이 되는 타입을 명시적으로 지정할 수 있다. 예를 들어서 useRef<HTMLButtonElement>()라고 하면 버튼 노드 타입으로 지정할 수 있다. 그리고 초기값이 undefined이면 HTML의 ref로 사용하기엔 타입이 맞지 않기 때문에, 이럴 때는 null로 지정하면 된다.

const buttonRef = useRef<HTMLButtonElement>(null);

profile
항상 웃어 봅시다

0개의 댓글