01. useRef
useState와 더불어 특정 값을 저장하기 위해 사용하는 대표적인 React hook
리랜더링과 상관없이 값을 기억하기 위해 사용되며(렌더링과 상관없이 변수를 유지), 자바스크립트 DOM API를 직접 사용하지 않고 DOM 요소에 직접 접근할 때 사용된다
02. 사용 방법
import "./App.css";
import { useRef } from "react";
function App() {
const ref = useRef("초기값"); //👈🏻초기 값
console.log("ref 1", ref);
ref.current = "바꾼 값"; //👈🏻변경 값
console.log("ref 1", ref);
return (
<div>
<p>useRef에 대한 이야기에요.</p>
</div>
);
}
export default App;
콘솔을 확인해 보면 아래와 같이 ref에 초기값과 바꾼값이 담겨있다
세번 출력되는 이유는 리액트의 Strict Mode(엄격모드) 때문이라고 한다
1️⃣ 컴포넌트가 처음 렌더링되면서 실행됨
- ref가 "초기값"으로 설정됨
👉🏻 첫 번째 console.log("ref 1", ref); 실행 → { current: "초기값" } 출력 - ref.current = "바꾼 값" 실행
👉🏻 두 번째 console.log("ref 1", ref); 실행 → { current: "바꾼 값" } 출력
2️⃣ React Strict Mode로 인해 개발 모드에서 App이 한 번 더 렌더링됨
- 위 과정이 다시 한 번 반복되면서 같은 값이 두 번 더 출력됨
- 그래서 "바꾼 값"이 세 번 출력됨
💡 여기서 나오는 current란?
useRef가 참조하고 있는 값(Reference)을 저장하는 속성
useRef를 선언하면 객체 형태로 {current: 값}이 만들어지고 내부의 current가 실제 값을 가르킴
03. useState와의 차이점
Ref는 State와 비슷한 역할을 하지만,
- useState는 변화가 일어나면 렌더링이 일어나고 내부 변수가 초기화 된다 👉🏻 리렌더링이 꼭 필요한 값에 사용한다
- useRef는 저장한 값들은 랜더링이 일어나지 않는다 = Ref값의 변화가 생겨도 렌더링으로 인해 내부 변수가 초기화되는 것을 막을 수 있다.
컴포넌트가 100번 렌더링 되더라도 Ref에 저장된 값은 유지된다 👉🏻 리렌더링을 발생시키지 않는 값을 저장할 때 사용한다
아래 예시 코드를 복사해서 실행해 보면 더 확실하게 차이를 알 수 있다
import "./App.css";
import { useRef, useState } from "react";
function App() {
const [count, setCount] = useState(0);
const countRef = useRef(0);
const plusStateCountButtonHandler = () => {
setCount(count + 1);
};
const plusRefCountButtonHandler = () => {
countRef.current++;
};
return (
<>
<div>
state 영역입니다. {count} <br />
<button onClick={plusStateCountButtonHandler}>state 증가</button>
</div>
<div>
ref 영역입니다. {countRef.current} <br />
<button onClick={plusRefCountButtonHandler}>ref 증가</button>
</div>
</>
);
}
export default App;
✔️ state가 변경되면 React는 컴포넌트를 다시 렌더링하며, 변경된 state 값을 반영하여 화면을 업데이트한다
✔️ 하지만 ref는 값이 변경되어도 컴포넌트가 다시 렌더링되지 않으며, 화면도 자동으로 업데이트되지 않는다
04. DOM 요소에 접근해보기
아래와 같이 간단히 input 값을 입력받는 구조를 만들어 보았다
import "./App.css";
function App() {
return (
<>
<div>
아이디 : <input type="text" />
</div>
<div>
비밀번호 : <input type="password" />
</div>
</>
);
}
export default App;
이때 화면이 렌더링 되고나면 input 범위에 마우스를 클릭해야 입력할 수 있다
하지만 useRef를 사용하면 자동으로 포커싱을 줄 수 있음
import { useEffect, useRef } from "react";
import "./App.css";
function App() {
const idRef = useRef("");
// 렌더링이 될 때
useEffect(() => {
idRef.current.focus();
}, []);
return (
<>
<div>
아이디 : <input type="text" ref={idRef} />
</div>
<div>
비밀번호 : <input type="password" />
</div>
</>
);
}
export default App;
이 코드를 보면 input요소에 참조할 ref를 생성하고,
컴포넌트가 처음 렌더링된 후 실행할 수 있도록 useEffect로 받아서 focus를 주고있다
왜 useEffect 안에서 focus()를 호출해야 할까?
idRef.current.focus(); // ❌ useEffect 없이 실행하면 에러 가능
위 코드처럼 useEffect 없이 실행하면 초기 렌더링 시 input요소가 아직 생성되지 않았기 때문에 null 오류가 발생할 수 있다
useEffect(() => {
idRef.current.focus(); //컴포넌트가 렌더링된 후 실행됨
}, []);
useEffect 사용 시 첫 렌더링(마운트) 이후 한 번만 실행되므로 안전하게 focus()를 적용할 수 있다
(별다른 이벤트 감지 없이 첫 렌더링 시 자동으로 실행되는 코드를 담는 역할을 한다)
'🩵 React > 학습 노트' 카테고리의 다른 글
[React🩵] 리액트 메모이제이션 총 정리! (0) | 2025.03.18 |
---|---|
[React🩵] Context (0) | 2025.03.14 |
[React🩵] useEffect와 components lifecycle (컴포넌트의 생명주기) (0) | 2025.03.14 |
[React🩵] Styled-components (0) | 2025.03.13 |
[React🩵] useState (0) | 2025.02.28 |