HTML과 JavaScript를 사용할 때, 특정 DOM을 선택해야 하는 상황에서 어떤 메서드를 사용하는가?
바로 DOM 함수인 getElementById(), querySelector() 를 사용한다.
React를 사용하는 프로젝트에서도 가끔 DOM을 직접 선택해야 하는 상황이 발생할 수 있다.
예를 들어, 특정 Element의 크기나 위치를 가져와야 할 때, 스크롤바 위치를 가져오거나 설정해줘야 할 때, focus를 설정해줘야 할 때 등, 다양한 상황이 있다. 또한 video.js, jw player와 같은 HTML5 비디오 관련 라이브러리를 사용할 때나 D3, chart.js 같은 그래프 관련 라이브러리를 사용하게 될 때도 특정 DOM에 라이브러리를 적용하기 때문에 DOM을 선택해야 하는 상황이 발생할 수 있다.
이때, ref를 활용한다!
함수형 컴포넌트에서 ref를 사용할 때는 useRef Hook을 사용한다.
클래스형 컴포넌트에서 ref를 사용할 때는 React.createRef()를 사용하거나 콜백함수를 사용한다.
본 포스팅은 함수형 컴포넌트에서 useRef Hook을 사용하여 특정 DOM을 선택하는 방법에 대해 알아볼 것이다.
#예제1
import React, { useState } from 'react';
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: '',
});
const { name, nickname } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
};
const onReset = () => {
setInputs({
name: '',
nickname: '',
});
};
return (
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange}
value={nickname}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;
위 코드를 그대로 작성했을 때 초기화 버튼을 누르게 되면, focus 되는 부분은 초기화 부분이다. focus 되는 부분을 다른 곳으로 이동시키고 싶을 때, React 자체적인 기능으로는 딱히 할 수 있는 방법이 없다.
이럴 때는 어쩔 수 없이 DOM에 직접 접근해야 한다.
1. useRef 사용법
// 1. useRef 작성
import React, { useState, useRef } from 'react';
// 2. ref 객체 생성
const nameInput = useRef();
// 3. 선택하고 싶은 DOM 내부 property에 ref 객체를 설정
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput} // 이 부분임
/>
// 4. DOM에 직접 접근
nameInput.current.focus();
nameInput.current 값은 현재 우리가 선택한 돔을 가리키게 된다. 따라서 이곳에 우리가 원하는 작업(focus 걸어주기)을 하면 되는 것이다.
아래는 전체 코드이다.
import React, { useState, useRef } from 'react';
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: '',
});
const nameInput = useRef();
const { name, nickname } = inputs;
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
};
const onReset = () => {
setInputs({
name: '',
nickname: '',
});
nameInput.current.focus();
};
return (
<div>
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange}
value={nickname}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;
또한 useRef는 이런식으로 DOM을 선택하는 것 외에 렌더링과 전혀 관계없는 변수 같은 것들을 관리하게 될 때에도 사용할 수 있다. setTimeout, setInterval 을 사용할 때 주어지는 id 값, 외부라이브러리를 사용하여 생성된 인스턴스를 담을 때, Scroll 위치를 알아야 할 때 등의 경우를 예로 들 수 있다.
중요한 것은 useRef로 관리하는 값은, 그 값이 바뀌어도 컴포넌트가 리렌더링이 되지 않는다는 것이다.
const nextId = useRef(0);
const onCreate = () => {
nextId.current += 1;
}
위와 같이 새로운 회원이 생성되었을 때 그 ID값을 useRef로 관리해줄 수 있다. 해당 값(회원의 ID값)이 바뀌어도 컴포넌트가 리렌더링이 될 필요가 없기 때문에, useRef로 관리해줄 수 있다.
물론 useState를 사용하여도 상관은 없다. 하지만 굳이 리렌더링이 돼야하는 값은 아니기 때문에, useRef를 활용하여 관리하는 것도 괜찮다는 것이다.
https://react.vlpt.us/ 강의자료를 참고하여 작성하였습니다.
'react.js' 카테고리의 다른 글
React에서 중요하게 알아야 할 몇가지 개념 정리 (0) | 2021.10.06 |
---|---|
useState, useReducer 차이점과 useReducer 사용방법 (2) | 2021.07.01 |
React 기록 시작 (0) | 2021.06.09 |