Frontend/TypeScript
[TypeScript | hooks] useRef 사용법( ref 객체 타입)
blueprint-12
2023. 3. 5. 19:42
Typescript에서 useRef를 사용할 때에는 용도에 따라서 타입지정이 달라지게 되는데 크게 두 가지로 나눌 수 있다.
1. 값 저장 용도 (current 객체 자체를 수정하기 위함)
: useRef를 로컬 변수 용도로 사용하는 경우이다.
- 제네릭: 값의 타입을 넣어준다.
- 초기값: 타입에 맞는 초기값을 할당해준다.
const count = useRef<number>(0);
const text = useRef<string>("")
2. DOM 취득 용도
- 제네릭: 참조하는 HTML 엘리먼트를 넣어준다.
- 초기값: null을 넣어준다.
// DOM button 참조: 제네릭으로 html엘리먼트(button) 설정. 초기값은 null로 설정
const buttonRef = useRef<HTMLButtonElement>(null);
// DOM input 참조 : 제네릭으로 html엘리먼트(input) 설정
const inputRef = useRef<HTMLInputElement>(null);
useRef - ref 객체 타입
1. 값 저장 용도: ref객체.current의 값을 수정 가능
React.MutableRefObject<제네릭>
2. DOM 취득 용도
ref 객체는 React.RefObject<제네릭> 타입이 되며, ref.current(참조하는 DOM)값 자체는 수정 불가
단, ref.current.속성(DOM객체.속성)은 수정이 가능하다.
Q. useRef는 수정 불가능한 RefObject<T>를 반환하는데, 왜 inputRef.current.value는 수정이 가능할까?
A. 정의상 current 프로퍼티만 readonly로, current 프로퍼티의 하위 프로퍼티인 value는 여전히 수정 가능하다.
readonly가 shallow하기 때문이다.
React.RefObject<HTMLButtonElement>
React.RefObject<HTMLInputElement>
결론
1번의 예시가 잘 와닿지 않아 찾아보니 useRef로 컴포넌트 안의 변수를 만들면 리렌더링을 발생하지 않고 초기화되지 않는 값을 관리할 수 있다고 한다.(heap 영역에 저장되는 일반적인 JS객체이기 때문에 react가 변경사항을 감지할 수 없다)
- 사용예시: setTimeout, setInterval의 id, 외부 라이브러리를 사용하여 생성된 인스턴스 scroll 위치 등 그냥 순수 JS로 렌더링마다 초기화되지 않는 변수가 필요할 때 사용하면 될 듯하다.
내가 주로 react 에서 useRef를 사용했던 상황은 주로 돔 요소를 가져와 focus를 주는 등.. 이 경우는 2번에 해당한다.
비제어 컴포넌트는 역시 2번을 활용하는 거 같다.
기능 | 제어 컴포넌트 | 비제어 컴포넌트 |
일회성 정보 검색 (예: 제출) | O | O |
제출 시 값 검증 | O | O |
실시간으로 필드값의 유효성 검사 | O | X |
조건부로 제출 버튼 비활성화 (disabled) | O | X |
실시간으로 입력 형식 적용하기 (숫자만 가능하게 등) | O | X |
동적 입력 | O | X |
all ref:
TypeScript React에서 useRef의 3가지 정의와 각각의 적절한 사용법
Type 'MutableRefObject<... | undefined>' is not assignable to type ... 에러 좀 그만 보자!
driip.me