컴포넌트가 특정 정보를 '기억'하도록 하고 싶지만 해당 정보가 새 렌더링을 촉발
하지 않도록 하려는 경우 ref를 사용할 수 있다.
import { useRef } from 'react';
const ref = useRef(0);
useRef훅을 가져와서 컴포넌트에 추가, 호출하고 참조할 초기값을 인자로 전달한다. 위 예에서는 0은 ref에 대한 초기값이다
useRef는 다음과 같은 객체를 반환한다
{
current: 0 // The value you passed to useRef
}
ref.current
속성을 통해 해당 ref의 현재값에 접근할 수 있다. 이 값은 읽기, 쓰기가 모두 가능하다.
ref값이 변해도 리렌더링이 일어나지 않는다. state와 마찬가지로 ref는 리렌더링 사이에 React에 의해 값이 유지된다.
state와 달리 설정자 함수를 사용하지 않고 변이할 수 있기 때문에, ref가 덜 '엄격'하다고 생각할 수 있다. ref는 자주 사용하지 않는 '탈출구'이다.
state와 ref로 구현된 카운터 버튼을 비교해보자.
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
You clicked {count} times
</button>
);
}
serCount가 실행되면서 리렌더링이 발생하고, 화면에 새로운 count를 반영한다.
하지만 ref로 구현한다면 리렌더링이 발생하지 않음으로 count는 변경되지 않는다.
import { useRef } from 'react';
export default function Counter() {
let countRef = useRef(0);
function handleClick() {
// This doesn't re-render the component!
countRef.current = countRef.current + 1;
}
return (
<button onClick={handleClick}>
You clicked {countRef.current} times
</button>
);
}
일반적으로 ref는 컴포넌트가 React로부터 '외부로 나가서' 외부 API, 즉 컴포넌트의 형상에 영향을 주지 않는 브라우저 API등과 통신해야 할 때 이다.
결론적으로 컴포넌트에 일부 값을 저장해야 하지만 렌더링 로직에는 영향을 미치지 않는 경우 ref를 선택하자
ref.current
가 언제 변경되는지 알지 못하기 때문에, 렌더링 중에 읽어도 컴포넌트의 동작을 예측하기 어렵다if (!ref.current) ref.current = new Thing()
과 같은 코드이다