앞에서부터 계속 다루고 있는 Hook API.. 강의를 들으면서, 혼자 토이 프로젝트를 진행하면서 그때그때 마주치게 되는 개념들을 하나씩 쓰다보니 Hooks 관련 포스트만 5개로 나눠져버렸다 😂
...아무튼 오늘은 간단하지만 가끔 헷갈리는! useRef에 대해서 자세히 다뤄보자 🏃♂️
useRef란 어떠한 특정 DOM을 선택할 수 있게 해준다. 코딩을 하다보면 DOM을 직접 선택해서 포커스를 주거나 특정 엘리먼트의 크기나 색상을 변경하는 경우가 있는데 그때 사용하는 것이다.
⚡DOM 이란?
HTML과 JavaScript를 이어주는 공간으로, 작성한 HTML을 JavaScript가 이해할 수 있도록 Object로 변환하는 것이다. 출처
(DOM에 대해서는 따로 다룰 예정이다!)
React 공식문서에 적혀있는 useRef의 기본 구조와 설명은 다음과 같다.
const refContainer = useRef(initialValue);
"useRef
는 .current
프로퍼티로 전달된 인자 (initialValue
)로 초기화된 변경 가능한 ref 객체를 반환한다. 반환된 객체는 컴포넌트의 전 생애 주기를 통해 유지될 것이다 "
설명만 봐서는 뭔소린지 도통 알수가 없다.. 예제를 통해서 이해해보자 🤯
import React, { useState, useRef } from "react";
import "./styles.css";
const App = () => {
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
const onChangename = (e) => {
setName(e.target.value);
};
const onChangenickname = (e) => {
setNickname(e.target.value);
};
// useRef 객체 생성
const ref = useRef();
const onClickReset = () => {
setName("");
setNickname("");
// 버튼 클릭시 지정한 위치에 focus 되도록
ref.current.focus();
};
return (
<div>
{/* 원하는 위치에 ref 값 설정한다 */}
<input value={name} onChange={onChangename} ref={ref} />
<input value={nickname} onChange={onChangenickname} />
<button onClick={onClickReset}>RESET</button>
<div>
<h3>결과</h3>
<h4>
{name} 의 별명은 {nickname} 입니다.
</h4>
</div>
</div>
);
};
export default App;
이름(name
)과 별명(nickname
)을 입력하면 화면에 띄우고, RESET 버튼을 누르면 이름과 별명을 초기화하고 원하는 위치 (위 코드에선 name
입력받는 input)로 focus 되도록 하는 예제이다.
핵심 코드만 한번 살펴보자!
1. useRef 객체를 생성한다
// useRef 객체 생성
const ref = useRef();
2. 선택하고 싶은 DOM에 ref 값으로 객체 넣기
{/* 원하는 위치(DOM)에 ref 값 설정한다 */}
<input value={name} onChange={onChangename} ref={ref} />
3. 객체를 통해 수행하고 싶은 작업 설정
const onClickReset = () => {
setName("");
setNickname("");
// 버튼 클릭시 지정한 위치에 focus 되도록
ref.current.focus();
};
RESET 버튼을 클릭하면 Focus가 위에서 설정한 name
input으로 이동하는 것을 확인 할 수 있다.
<input value={nickname} onChange={onChangenickname} ref={ref} />
만약 nickname
input에 ref를 설정하게 되면 결과는 다음과 같이 변하게 되는 것을 확인 할 수 있다.
useRef 특정 DOM을 선택하는 용도 이외에도 Component 안에서 조회 및 수정이 가능한 변수를 관리하는 용도로도 사용된다.
하지만 useRef 이용해서 변수를 업데이트 하게 되면 해당 Component가 리렌더링 되지 않기 때문에 리렌더링을 원한다면 callback ref를 사용해야 한다.
but ! 굳이 리렌더링이 필요없는 변수를 다룰때는 useRef를 사용하는 것이 효율적이다!
useRef를 통해 관리되는 변수가 주로 쓰이는 곳
setTimeout
,setInterval
을 통해 만들어진id
- scroll의 위치
- 배열에 새 항목이 추가 될 때 필요한 고유 key 값
- 외부 라이브러리를 사용하여 생성된 인스턴스
import React, {useRef} from 'react';
import UserList from './UserList';
const App = () => {
const users = [
{
id:1,
name: '김채원'
},
{
id:2,
name: '푸푸'
},
{
id:3,
name: '쌈무'
}
];
const nextId = useRef(4);
const onCreate = () => {
// 배열에 항목 추가하는 부분 생략
nextId.current += 1;
};
return <UserList users={users}/>;
}
export default App;
현재 users
라는 배열에 3명의 user가 존재하기 때문에 다음에 추가되면 해당 user의 id = 4 가 되므로 const nextId = useRef(4);
를 통해 .current
의 기본값을 설정해준다.
그 후 배열을 추가하는 부분에 새로 추가되는 배열의 id
값을 nextId.current += 1;
을 통해 1 증가시키고 해당 값을 넣어주면 된다.
여기서 드는 한가지 의문점..
let nextId = 4;
이렇게 변수를 선언하고 값을 증가시켜주면 되는거.. 아닌가??
할수도 있지만 함수형 컴포넌트 안에서 변수를 위처럼 선언하게 되면 리렌더링 될 때마다 값이 4로 초기화 되기 때문에 배열에 대참사가 일어날 수 있다 😵
이해가 잘되네요 감사합니다~