useRef : 리액트 훅 사용법
useRef는 React에서 참조(ref)를 관리하는 데 사용하는 훅이다.
주로 DOM요소나 값을 참조하고자 할 때 사용된다.
useRef를 사용하면 컴포넌트가 렌더링될 때마다 값이 초기화 되지 않고 계속 유지된다.
useRef는 값의 변경을 렌더링에 영향을 미치지 않게 추적할 수 있다. 일반적인 상태 변수(useState)는 값이 변경될 때마다 컴포넌트를 다시 렌더링하지만, useRef는 값을 바꾸더라도 렌더링을 트리거하지 않는다.
예를들어, DOM요소나 타이머 ID같은 것을 추적할 때 렌더링을 다시 트리거하지 않으면서 상태를 유지할 수 있다.
useRef의 기본 개념
- useRef는 객체를 반환한다. 이 객체는 current라는 속성을 가지고 있으며, 이 속성에 원하는 값을 저장할 수 있다.
- DOM 요소에 대한 참조를 얻을 때 주로 사용되지만, 일반 JavaScript값을 저장하는 데도 사용될 수 있다.
기본문법
const myRef = useRef(initialValue);
initialValue : useRef가 처음 생성될 때 초기화할 값
myRef.current : useRef의 반환 객체에서 참조할 수 있는 값
useRef 훅은 객체를 반환한다.
이 객체는 {current:값} 형태로 current라는 속성을 포함하고있다.
이 속성에 처음에는 initialValue값을 저장되며 이후 current를 통해 해당 값이 접근하거나 업데이트 할 수 있다.
current는 내부에 저장된 값을 의미한다.
예를 들어, useRef로 input의 참조를 저장할 수 있다면, current 속성에 실제 DOM 요소가 저장된다.
즉 current는 값을 저장하는 컨테이너 역할을 한다.
예시
const myRef = useRef(0); // 초기값 0을 저장
console.log(myRef.current); // 0
myRef.current = 5; // 값을 변경
console.log(myRef.current); // 5
여기서 myRef.current는 처음에 0으로 설정되어있고, 나중에 5로 변경된다.
이 값은 컴포넌트를 재렌더링 하지 않으면서 유지 된다.
주로 사용하는 경우
1. Dom 참조 : useRef는 DOM요소를 직접 참조하고자 할 때 자주 사용된다. 예를 들어, 버튼 클릭 시 DOM에 직접 접근해야 할 때 유용하다.
2. 렌더링 없이 값 저장 : useRef는 값이 변경되어도 컴포넌트가 다시 렌더링되지 않게 할 수 있다. 예를들어 타이머의 ID나 이전 값을 저장할 때 유용하다.
DOM 참조 예시
useRef를 사용해서 DOM 요소에 직접 접근할 수 있다.
import React, { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
const handleFocus = () => {
// input 요소에 직접 접근하여 포커스를 설정
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleFocus}>Focus the input</button>
</div>
);
}
export default FocusInput;
위 예시에서 inputRef는 input DOM 요소를 참조한다. 버튼을 클릭하면 inputRef.current를 통해 해당 input요소에 접근하여 포커스를 설정할 수 있다.
렌더링 없이 값 저장 예시
useRef는 값을 저장하는 데 사용되며, 해당 값이 변경되더라도 컴포넌트가 다시 렌더링되지 않는다.
import React, { useState, useRef } from 'react';
function Timer() {
const [count, setCount] = useState(0);
const timerRef = useRef(null); //타이머 ID를 저장할 ref
//타이머 시작 함수
const startTimer = () => {
//타이머 ID를 ref에 저장
timerRef.current = setInterval(() => {
setCount((prevCount) => prevCount + 1); //매 초마다 count 증가
}, 1000);
};
//타이머 멈추는 함수
const stopTimer = () => {
clearInterval(timerRef.current);
};
return (
<div>
<p>Timer: {count}s</p>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
</div>
);
}
export default Timer;
- 타이머 ID는 timerRef.current에 저장된다.
- startTimer 함수는 setInterval로 타이머를 시작하고 그 ID를 timerRef.current에 저장한다.
- stopTimer 함수는 clearInterval을 사용하여 timerRef.current에 저장된 ID를 기준으로 타이머를 멈춘다.
- 타이머 값(count)은 useState로 관리되고, 값이 변경될 때마다 컴포넌트가 렌더링된다.
- timerRef는 타이머 ID를 추적하며, 값이 바뀌어도 렌더링을 트리거하지 않는다.
이처럼 useRef는 타이머 ID같은 값을 저장하고 추적하는데 유용하며, 값이 변경되어도 컴포넌트를 다시 렌더링하지 않도록 할 수 있다.
※ 타이머 ID : setInterval 또는 setTimeout 함수에서 변환하는 고유한 식별자 Id
이 ID는 타이머가 실행될 때마다 생성되며, 타이머를 정지 하려면 이 ID를 사용해야 한다.
useRef를 사용해야 하는 이유
- DOM 참조 : 특정 DOM 요소에 접근할 때, 예를 들어, input, div, canvas등의 요소에 대해 직접적으로 제어 할 수 있다.
- 렌더링 최적화 : 값이 변경되더라도 컴포넌트를 재렌더링하지 않게 하여 성능을 최적화할 수 있다.
- 비동기 작업에서 상태 저장 : 비동기 작업(예: setTimeout, setInterval)에서 이전 상태를 저장하고, 리렌더링 없이 해당 값을 추적할 수 있다.
정리
useRef는 UI를 변경하지 않는 값의 추적이나 외부 상태(예: 타이머ID, DOM요소 등 )을 관리하는 데 유용하다.
이 값은 변할 수 있지만, 렌더링을 트리거하지 않으므로 UI에 영향을 주지 않고 필요한 작업을 할 수 있다.