useRef는 React에서 제공하는 훅 중 하나로, 함수형 컴포넌트에서 참조(reference)를 위한 객체를 생성하는 데 사용됩니다.
useRef를 사용하여 생성된 객체는 기본적으로 두 가지 프로퍼티를 가지고 있습니다. 첫 번째는 current 프로퍼티로, 이 값은 레퍼런스 객체가 참조하는 실제 값입니다. 두 번째는 current 값을 변경할 수 있는 current 프로퍼티의 세터(setter) 함수입니다.
useRef를 사용하여 생성된 레퍼런스 객체는 컴포넌트가 렌더링될 때마다 새로운 객체가 생성되는 것이 아니라, 이전에 생성된 객체를 재사용합니다. 따라서, 이를 사용하여 컴포넌트의 상태(state)가 변경되었을 때 값을 저장하거나, 이전 값에 접근하는 등의 기능을 구현할 수 있습니다.
주로 다음과 같은 경우에 useRef를 사용합니다.
예를 들어, useRef를 사용하여 이전 상태값을 저장하고 출력하는 코드는 다음과 같습니다.
const {useState, useRef} = React;
function Example() {
const [count, setCount] = useState(0);
const prevCountRef = useRef(0);
const handleIncrement = () => {
prevCountRef.current = count;
setCount(count + 1);
};
return (
<div>
<p>Count: {count}</p>
<p>Previous Count: {prevCountRef.current}</p>
<button onClick={handleIncrement}>Increment</button>
</div>
);
}
위 예시에서 prevCountRef는 useRef를 사용하여 생성된 레퍼런스 객체입니다. handleIncrement 함수에서 prevCountRef.current에 count 값을 저장하고, 렌더링 결과에서는 이전 상태값을 출력합니다. 이렇게 useRef를 사용하여 이전 값에 접근하는 것은 클래스형 컴포넌트에서 componentDidUpdate 메서드에서의 이전 값 비교와 비슷한 역할을 합니다.
const{useState, useRef} = React;
function Counter(){
const[count, setCount] = useState(0);
let variable = 0;
const countRef = useRef(0);
console.log('Counter 랜더링 됨...');
const increaseCount = () => {
setCount(count + 1);
};
const increaseVariable = () => {
variable += 1;
console.log(`variable : ${variable}`);
}
const increaseCountRef = () => {
countRef.current = countRef.current + 1;
console.log(`current : ${countRef.current}`);
}
return(
<>
<h1> count : {count} </h1>
<h1> variable : {variable}</h1>
<h1> countRef.current : {countRef.current}</h1>
<button onClick={increaseCount}>count 증가</button>
<button onClick={increaseVariable}>variable 증가</button>
<button onClick={increaseCountRef}>countRef 증가</button>
</>
)
}
ReactDOM.createRoot(document.getElementById('root')).render(<Counter/>);
/* 특정 input에 포커스를 주고 싶을 경우 DOM에 접근해야 하는데 이를 위해서도 useRef를 사용할 수 있다. */
const { useState, useRef, useEffect } = React;
function LoginComponent(){
const [form, setForm] = useState({
username : '',
password : ''
});
const usernameRef = useRef();
// 랜더링 이전 동작이기 때문에 최초 출력은 undefined가 나옴
console.log(usernameRef);
// 초기 화면 랜더링 후 출력 확인
useEffect(() => {console.log(usernameRef)
//포커스 설정
usernameRef.current.focus();
},[]);
const onChangeHandler = (e) => {
setForm({
...form,
[e.target.name] : e.target.value
});
}
return (
<>
<input
type="text"
name="username"
ref={usernameRef}
placeholder="username"
value = { form.username }
onChange = {onChangeHandler}
/>
<br/>
<input
type='password'
name="password"
placeholder="password"
value = {form.password}
onChange={onChangeHandler}
/>
<br/>
<button>로그인</button>
</>
)
}
ReactDOM.createRoot(document.getElementById('root')).render(<LoginComponent/>);
위 코드는 React에서 useRef를 사용하여 input 요소에 포커스를 주는 방법을 보여줍니다.
컴포넌트 함수 내부에서 useState, useRef, useEffect를 사용합니다. LoginComponent 함수 내부에는 form이라는 상태 값과 usernameRef 변수가 있습니다.
form은 초기 값으로 빈 문자열로 초기화된 username과 password 값을 가진 객체입니다.
usernameRef는 useRef를 사용하여 생성한 변수입니다. 이 변수를 사용하여 React에서 DOM 요소에 직접 접근할 수 있습니다. usernameRef 변수는 input 요소의 ref 속성으로 사용됩니다.
useEffect 훅은 컴포넌트 랜더링 이후 한 번만 실행됩니다. useEffect 훅의 두 번째 매개변수로 빈 배열을 전달하여 컴포넌트가 처음으로 랜더링될 때만 실행되도록 합니다.
useEffect 훅의 콜백 함수 내부에서는 usernameRef.current.focus()를 사용하여 input 요소에 포커스를 줍니다.
onChangeHandler 함수는 input 요소에 입력된 값을 form 상태에 업데이트합니다.
컴포넌트가 랜더링될 때, usernameRef 변수는 undefined이므로, useEffect 훅에서 usernameRef 변수를 출력해보면 먼저 undefined가 출력됩니다. 그러나 useEffect 훅의 두 번째 매개변수로 빈 배열을 전달하여 컴포넌트가 처음으로 랜더링될 때만 실행되도록 하였기 때문에, 화면이 랜더링된 후, usernameRef 변수에는 실제 DOM 요소의 참조가 할당됩니다. 이후 useEffect 훅에서 usernameRef 변수를 출력하면 실제 DOM 요소를 가리키는 것을 확인할 수 있습니다.