front-end / / 2024. 3. 1. 20:24

[react] 타입스크립트에서 ref 사용하기

이번에는 ref에 타입스크립트를 적용하는 방법을 알아보자.

다음 컴포넌트를 한번 보자. input 요소에 ref가 참조가 걸려있다.

const UserSearch: React.FC = () => {
  const inputRef = useRef();
  const [name, setName] = useState("");
  const [user, setUser] = useState<{ name: string; age: number } | undefined>();

  const onClick = () => {
    const foundUser = users.find((user) => {
      return user.name === name;
    });

    setUser(foundUser);
  };

  return (
    <div>
      User Search
      <input
        ref={inputRef}
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <button onClick={onClick}>Find User</button>
      <div>
        {user && user.name}
        {user && user.age}
      </div>
    </div>
  );
};

여기서 input 속성인 ref에서 발생하는 오류를 한번 보자.

마우스 오버를 하면 오류가 보이는데 그냥 봐서는 이해가 잘 되지 않는다. ref를 만들 때 HTML 요소를 참조하고 그 사이에 <>으로 ref가 참조하는 타입을 정의를 한다. 여기서는 <HTMLInputElement>를 추가한다.

const inputRef = useRef<HTMLInputElement>();

HTML 요소는 다른 인터페이스이다. HTMLInputElement를 클릭해서 세부 내용을 한번 보자.

...
interface HTMLHeadElement extends HTMLElement {}
interface HTMLHRElement extends HTMLElement {}
interface HTMLHtmlElement extends HTMLElement {}
interface HTMLIFrameElement extends HTMLElement {}
interface HTMLImageElement extends HTMLElement {}
interface HTMLInputElement extends HTMLElement {}
...
interface HTMLDivElement extends HTMLElement {}
...

여기서 HTMLElement에 대한 모든 요소의 인터페이스가 정리되어 있다. HTMLInputElement을 추가했는데도 ref에 오류는 그대로 표시가 된다. ref에 수정해야 할 것이 아직 남아 있다는 뜻이다.

우선, 화면에 컴포넌트를 렌더링할 때, ref를 정의하지만 어느 엘리먼트에 참조해야 할지는 모른다. 즉, 타입스크립트 입장에서는 알 수가 없다는 뜻이다.

즉, 소스코드에서 input에서 ref={inputRef} 속성을 삭제를 하면 inputRef는 참조를 해야 할 대상이 없어진다. 타입스크립트는 ref가 어떤 HTML 엘리먼트에 참조를 하지 못할 수도 있다는 것을 알고 있다. 그래서 useRef를 생성할 때 null이 될 수 있다고 타입스크립트는 판단한다. 그래서 useRef에서는 아래와 같이 null을 추가해야 한다. 그리고 기본값도 null로 설정해야 한다.

const inputRef = useRef<HTMLInputElement | null>(null);

여기서 컴포넌트가 최초 로딩되었을 때 input에 focus를 설정해보자. 아래와 같이 useEffect를 사용하면 된다.

useEffect(() => {
    inputRef.current?.focus();
}, []);

inputRef.current는 null이 될 수 있기 때문에 inputRef.current?로 사용하였다.

이런식으로 ref에는 ref가 참조하는 HTMLElement의 타입을 추가하면 되고 null이 될 수 있다는 것을 생각해야 한다.

참고

https://www.udemy.com/course/react-and-typescript-build-a-portfolio-project

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유