useRef
는 React의 훅(Hook) 중 하나로, DOM 요소에 접근하거나, 렌더링과 관계없이 값을 저장하고 유지하는 데 사용
리렌더링을 발생시키지 않고 특정 값을 유지하고 싶을 때 유용합니다.
➡️ 즉, 컴포넌트가 계속해서 렌더링이 되어도 컴포넌트가 언마운트 되기 전까지는 값을 그대로 유지할 수 있음
리렌더링을 발생시키지 않고 특정 값을 유지하고 싶을 때 유용
[useState]
State의 변화 -> 렌더링 - 컴포넌트 내부 변수들 초기화
[useRef]
Ref 의 변화 -> No 렌더링 -> 변수들의 값이 유지됨
State의 변화 -> 렌더링 -> 그래도 Ref의 값은 유지됨
대표적으로 input 이 있을 때, 해당 input 칸을 직접 마우스로 클릭하지 않아도 커서가 자동으로 focus 되게끔 가능
const countRef = useRef(0) // 초기 값을 0 또는 null(빈공간) 으로 설정
< element ref={countRef} /> // Dom 주소를 담고 싶은 요소에 ref 속성으로 연결해주기
console.log(countRef) // { current : 0 } => current 값에 초기값이 나옴
//이때 current 값에 접근하기 위해서는 ...
countRef.current === < element ref={countRef} />
📍 예제
useRef
를 사용하면 컴포넌트가 리렌더링될 때도 값이 유지되지만, 값이 변경되어도 리렌더링이 발생하지 않음
import { useRef, useState } from 'react';
import './App.css'
const App = () => {
const [count, setCount] = useState(0);
const countRef = useRef(0);
console.log(' 렌더링. . . ');
const increaseCountState = () => {
setCount (count + 1);
};
const increaseCountRef = () => {
countRef.current = countRef.current + 1;
console.log('Ref: ', countRef.current);
};
return (
<div>
<p>State: {count}</p>
<p>Ref: {countRef.current}</p>
<button onClick={increaseCountState}>State Up</button>
<button onClick={increaseCountRef}>Ref Up</button>
</div>
)
}
export default App;
🔮 State Up
버튼을 눌렀을 때는 화면에 바로 리렌더링, Ref Up
버튼을 눌렀을 때는 화면에 즉시 리렌더링 되지 않음
Ref Up
버튼을 3번 누르면 (Ref: 3) 이 저장되며, state Up
버튼을 누르면 Ref 값이 3으로 저장된 상태로 화면에 리렌더링이 실행되므로useState
와 달리 useRef
는 상태 변화가 UI 업데이트를 유발하지 않습니다.🔖 추가 예제 - 잘못된 예제 (❌)
import { useEffect, useState } from 'react';
import './App.css'
const App = () => {
const [count, setCount] = useState (1) ;
const [renderCount, setRenderCount] = useState (1);
useEffect(() => {
console. log('렌더링!') ;
setRenderCount (renderCount + 1) ;
})
return (
<div>
<p>Count: {count} </p>
<button onClick={() => setCount (count + 1 ) }>올려</button>
</div>
) ;
}
export default App;
🔮 위처럼 코드 작성 시 useEffect
부분이 state가 자동적으로 계속 리렌더링 되어 무한 렌더링 됨.
🔖 추가 예제 - 올바른 예제 (⭕️)
import { useEffect, useRef, useState } from 'react';
import './App.css'
const App = () => {
const [count, setCount] = useState (1) ;
const renderCount = useRef(1);
useEffect(() => {
renderCount.current = renderCount.current + 1
console.log('렌더링 수 : ', renderCount.current)
})
return (
<div>
<p>Count: {count} </p>
<button onClick={() => setCount (count + 1 ) }>올려</button>
</div>
) ;
}
export default App;
🔮 위처럼 state
영역을 useRef
로 변경하여 작성 시 정상 작동.
📍 예제
useRef
는 주로 DOM 요소에 직접 접근할 때 많이 사용됩니다.
import { useRef } from "react";
function FocusInput() {
const inputRef = useRef(null); // 초기값 null 설정
const handleFocus = () => {
inputRef.current.focus(); // input 요소에 포커스 주기
};
return (
<div>
<input ref={inputRef} type="text" placeholder="이름을 입력하세요" />
<button onClick={handleFocus}>포커스</button>
</div>
);
}
export default FocusInput;
🔖 추가 예제
import { useEffect, useRef, useState } from 'react';
import './App.css'
const App = () => {
const inputRef = useRef();
useEffect (() => {
// console. log (inputRef);
inputRef.current.focus ();
}, []);
const login = () => {
alert(`환영합니다 ${inputRef.current.value}!`) ;
inputRef.current.focus();
}
return (
<div>
<input ref={inputRef} type="text" placeholder="username" />
<button onClick={login}>로그인</button>
</div>
);
};
export default App;
🔮 페이지를 첫 렌더링 시 focus
가 input
에 잡혀서 input 에 마우스 커서 가 있고,
입력한 내용이 alert
로 실행되며 해당 alert 종료 시에도 focus 가 input에 있음
비교 항목 | useRef | useState |
---|---|---|
값 변경 시 리렌더링 여부 | ❌ 리렌더링 없음 | ✅ 리렌더링 발생 |
값 유지 여부 | ✅ 유지됨 | ✅ 유지됨 |
DOM 요소 접근 가능 여부 | ✅ 가능 | ❌ 불가능 |
useRef는 상태 관리를 위한 것이 아니라, 렌더링과 무관하게 값 유지 및 DOM 요소 접근을 위한 훅으로,
적절히 활용하면 불필요한 리렌더링을 방지하고 성능을 최적화할 수 있다.