html과 js를 사용할 때에는 특정 DOM을 선택해야하는 상황에 getElementById, querySelector 같은 DOM Selector 함수를 사용해서 DOM 을 선택했다. 리액트를 사용하는 프로젝트에서도 DOM을 직접 선택해야 하는 일이 발생하는데, 그럴 때 ref
를 사용하고, 함수형 컴포넌트에서는 useRef
라는 Hook 함수를 사용한다.
초기화 버튼을 클릭했을 때 이름 input 에 포커스가 잡히도록 useRef
를 사용하여 기능 구현
import React, { useState, useRef } from "react";
export default function InputTest() {
const [inputs, setInputs] = useState({ name: "", nickname: "" });
const nameInput = useRef();
// useRef()로 Ref 객체를 만듬
const { name, nickname } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
};
const onReset = () => {
setInputs({
name: "",
nickname: "",
});
nameInput.current.focus();
// 만든 Ref객체.current값은 DOM을 가리킴
// onReset함수 실행 시 ref로 설정한 input에 포커스
};
return (
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
// 선택하고 싶은 DOM에 ref값으로 설정
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange}
value={nickname}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name}({nickname})
</div>
</div>
);
}
본질적으로 useRef는 .current 프로퍼티에 변경 가능한 값을 담고 있는 “상자”와 같다.
useRef
Hook 은 DOM 을 선택하는 용도 뿐만 아니라, 다른 용도로도 사용된다. 컴포넌트 안에서 조회 및 수정 할 수 있는 변수를 관리하는 것이다.
기본적으로 리액트 컴포넌트는 내부 상태(state)가 변할 때마다 다시 랜더링이 된다. 대부분의 경우, 상태가 변할 때 마다 React 컴포넌트 함수가 호출되어 화면이 갱신되기를 바랄 것이다. 하지만 다시 랜더링이 되더라도 기존에 참조하고 있던 컴포넌트 함수 내의 값이 그대로 보존되야 하는 경우가 있다. (ex, 자동 카운팅)
이때 useRef
를 사용하여 컴포넌트가 리렌더링 될 때 계속 기억할 수 있는 값을 관리할 수 있다.
주로 다음과 같은 상황에서 사용한다.
배열에 새 항목을 추가할 때, 새 항목에서 사용할 고유 id를 관리할 용도로 useRef를 사용해본다. 먼저 App에서 배열을 선언하고, UserList에게 props로 전달해준다.
App.js
import React, { useRef } from "react";
import UserList from "./UserList";
function App() {
const users = [
{
id: 1,
username: "su",
email: "susu@gmail.com",
},
{
id: 2,
username: "liz",
email: "lili@gmail.com",
},
{
id: 3,
username: "ro",
email: "ro@gmail.com",
},
];
const nextId = useRef(4);
// 이 값이 바뀐다고 해서 컴포넌트가 리렌더링 될 필요가 없기 때문에 useRef 사용
const onCreate = () => {
console.log(nextId.current); //4
nextId.current += 1; // 현재값에 +1
};
return <UserList users={users} />;
}
export default App;
useRef()
를 사용할 때 파라미터를 넣어주면, 그 값이 .current
의 기본값이 된다.
UserList.js
import React from "react";
function User({ user }) {
// props로 user값을 받아옴
return (
<div>
<b>{user.username}</b> <span>{user.email}</span>
</div>
);
}
export default function UserList({ users }) {
return (
<div>
{users.map((user) => (
<User user={user} key={user.id} />
))}
</div>
);
}