[TIL/React] useRef 기본
What is useRef
?
useRef는 렌더링에 필요하지 않은 값을 참조할 수 있는 React Hook입니다.
- react 공식문서
말그대로 렌더링에 사용하지 않는 값을 참조하는 훅이며, 또는 DOM을 조작하기 위해서 주로 사용한다. 이 글에서는 가장 기본적인 사용법인 렌더링하지 않는 데이터 저장에 대해 알아본다.
컴포넌트가 일부 데이터를 기억하길 바라지만, state처럼 렌더링을 유발하지 않도록 하려면 ref를 사용한다.
사용법
기본적인 사용법은 다음과 같다.
// 1. react로부터 useRef를 가져온다
import { useRef } from 'react';
// 2. state처럼 초깃값을 함수에 파라미터로 전달한다.
const ref = useRef(0);
useRef
는 다음처럼 객체를 반환한다.
{
current: 0 // 초기화 값
}
ref.current
를 통해서 해당 ref의 current 값에 접근할 수 있다.숫자, 문자열, 함수 등 모든 것을 가리킬 수 있다. (객체에 저장하는 거임)
state의 경우, 해당 값이 변경되면 렌더링이 발생하지만, ref의 경우, 값이 변경되어도 UI 렌더링이 발생하지는 않는다. state와 결합하여 사용되기도 하며 다음은 가장 대표적인 예시 중 하나인 countdown 예시이다.
import { useState, useRef } from 'react';
export default function Stopwatch() {
const [startTime, setStartTime] = useState(null);
const [now, setNow] = useState(null);
// 타이머 구현을 위해 interval을 생성하는데, setInterval 함수를 ref로 저장해준다.
// clearInterval을 통해 타이머를 멈추기 위해서 ref에 저장을 한 예시임
const intervalRef = useRef(null);
function handleStart() {
setStartTime(Date.now());
setNow(Date.now());
// 타이머가 시작되면 intervalRef의 current 값에 setInterval()함수를 저장한다.
clearInterval(intervalRef.current);
intervalRef.current = setInterval(() => {
setNow(Date.now());
}, 10);
}
function handleStop() {
// 종료 이벤트가 발생하면, intervalRef에 저장되어있던 interval을 종료할 수 있다.
clearInterval(intervalRef.current);
}
let secondsPassed = 0;
if (startTime != null && now != null) {
secondsPassed = (now - startTime) / 1000;
}
return (
<>
<h1>Time passed: {secondsPassed.toFixed(3)}</h1>
<button onClick={handleStart}>
Start
</button>
<button onClick={handleStop}>
Stop
</button>
</>
);
}
useRef의 내부 동작
공식 문서에서는 useRef를 useState로 구현한 예시를 보여준다.
function useRef(initialValue) {
// setter 함수를 사용하지 않고 ref라는 state에 저장된 객체만 뱉는다.
const [ref, ununsed] = useState({ current: initialValue })
return ref;
}
정리
Refs는 렌더링이 필요하지 않은 데이터 저장을 위해 사용
ref는 current라는 프로퍼티에 값을 저장하는 객체임
컴포넌트 렌더링 간에 데이터를 유지할 수 있음 (렌더링 발생해도 값이 초기화되지 않는다.)
ref의 current 값을 변경해도 리렌더링이 발생하지 않는다.