Frontend/React

Typescript - useRef() 사용시 type 설정

rachel_13 2022. 12. 13. 07:25

일반적으로 React에서 ref는 HTML 엘리먼트를 할당하는데 사용된다.

DOM에 직접 접근하기 위해 ref를 사용하기도 한다. (Javascript에서 고유 id 부여하는 것처럼)

 

그런데, 함수형 컴포넌트에서 타입스크립트 사용시 무심코 useRef 훅을 사용하게 되면 typeError를 만나게 된다.

가장 좋은 방법은 ref를 null로 초기화하는 것이다.  또한 유형 인수를 사용하여 ref 속성으로 사용되는 요소에 대해 각각 HTMLInputElement 유형으로 ref를 캐스팅해야 합니다.

import * as React from 'react';

const App = () => {
  const ref = React.useRef<HTMLInputElement>(null);

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

  return <input ref={ref} />;
};

export default App;

 

HTML 요소의 고유한 불변값으로 ref를 사용하는 경우, 값을 캡처하기 위해 ref를 인스턴스 변수로 사용해야 할 경우가 있다.

아래 예시의 경우, ref는 모든 클릭 이벤트를 추적한다.

import * as React from 'react';

interface CounterTracker {
  increment: number;
  decrement: number;
}

const App = () => {
  const [count, setCount] = React.useState<number>(0);

  const ref = React.useRef<CounterTracker>({
    increment: 0,
    decrement: 0,
  });

  const handleIncrement = () => {
    ref.current.increment++;
    setCount(count + 1);
  };

  const handleDecrement = () => {
    ref.current.decrement++;
    setCount(count - 1);
  };

  return (
    <>
      <button onClick={handleIncrement}>+</button>
      <button onClick={handleDecrement}>-</button>
      <div>Count: {count}</div>

      <div>
        Buttons {ref.current.increment + ref.current.decrement}{' '}
        times clicked
      </div>

      <div>Increment clicked: {ref.current.increment}</div>
      <div>Decrement clicked: {ref.current.decrement}</div>
    </>
  );
};

export default App;

 

Typescript in React 에서 useRef를 사용하는 일은 2가지다.

1. DOM 접근 용도

DOM 요소에 액세스하기 위해 null을 초기값으로 사용한다.  이 경우 반환된 참조에는 React에서 관리하는 읽기 전용 .current가 있다.  TypeScript는 이 ref를 요소의 ref prop 속성으로 제공한다.

function Foo() {
  // HTML 요소는 가능하면 상세히 선언 한다. ex) HTMLDivElement
  // 반환 : RefObject<HTMLDivElement>
  const divRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    // ref.current = null
    // ref로 선언한 요소들만 조건부 랜더링
    if (!divRef.current) throw Error("divRef is not assigned");

    doSomethingWith(divRef.current);
  });

  // DOM 요소에 ref 할당 - React에서 핸들링
  return <div ref={divRef}>etc</div>;
}

2. 가변 값 참조(Mutable Value)

function Foo() {
  // 반환 : MutableRefObject<number | null>
  const intervalRef = useRef<number | null>(null);

  // ref를 조작할 수 있다
  useEffect(() => {
    intervalRef.current = setInterval(...);
    return () => clearInterval(intervalRef.current);
  }, []);

  // 이 때의 ref는 ref.props로 전달되지 않는다는 사실에 유의
  return <button onClick={/* clearInterval the ref */}>Cancel timer</button>;
}

 

참고 : https://www.robinwieruch.de/typescript-react-useref/

         https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/hooks/#useref

'Frontend > React' 카테고리의 다른 글

pnpm peer dependencies auto-install  (0) 2023.03.02
pnpm cache clean  (0) 2023.03.02
[React] + [Typescript + Emotion]에서 props 넘기는 방법  (0) 2022.09.10
[Redux]미들웨어(middleware)  (0) 2022.08.14
[Redux] 관심사의 분리(SoC)  (0) 2022.08.14