useRef 사용법 및 ref로 HTML 엘리먼트에 접근/제어하기

Dodam·2023년 9월 15일
0

[React]

목록 보기
5/12
post-thumbnail

useRef는 언제 사용할까?

1. 특정한 값을 저장할 때

state를 사용할 경우, state가 변경될 때 리렌더링되면서 컴포넌트 내부 변수가 초기화된다.
따라서, 변하지 않는 값이 필요하다면 useRef를 사용할 수 있다.
useRef의 값이 변경될 때는 리렌더링이 되지 않는다. 즉, state 대신 useRef를 사용하면 불필요한 렌더링을 막을 수 있고, 컴포넌트가 렌더링되어도 useRef의 값이 변경되지 않고 유지된다.

2. DOM 요소에 접근할 때

예를 들어 input창에 focus()를 주고 싶다면 useRef를 사용할 수 있다.
input 박스를 마우스로 클릭하지 않아도 자동으로 포커스가 맞춰져 있다면,
불필요한 동작(ex. 마우스 클릭 등) 없이 키보드를 바로 입력할 수 있는 등의 효율적인 작업이 가능하다.

1. useRef로 특정한 값 저장하기

대부분의 경우, 상태가 변할 때마다 React 컴포넌트 함수가 호출되어 화면이 갱신되기를 바란다.
하지만 간혹 다시 렌더링이 되더라도 기존에 참조하고 있던 컴포넌트 함수 내의 값이 그대로 보존되어야 하는 경우도 있다.

예를 들어, 자동으로 카운팅이 되는 컴포넌트를 작성한다고 할 때 다음과 같이 컴포넌트를 작성할 수 있다.


만약 여기서 카운트를 자동으로 시작하지 않고, 버튼을 이용하여 시작 및 정지하고 싶다면 startConter와 stopCounter를 생성하여 코드를 다음과 같이 수정할 수 있다.
단, 여기서 선언된 intervalId 변수를 startCounter() 함수와 stopCounter() 함수가 공유할 수 있도록 intervalId 변수를 두 함수 밖에서 선언해줘야 한다.

하지만 그렇게 할 경우, count 상태값이 바뀔 때마다 컴포넌트 함수가 호출되어 intervalId도 매번 새로운 값으로 바뀌게 된다.

이와 같은 문제를 해결하기 위해서 다음과 같이 useRef 함수를 사용할 수 있다.

ex) 리렌더링 되어도, 동일한 참조값 유지하기

useRef 함수는 current 속성을 가지고 있는 객체를 반환하는데,
인자로 넘어온 초기값을 current 속성에 할당한다.
이 current 속성은 값을 변경해도 상태를 변경할 때처럼 React 컴포넌트가 다시 렌더링되지 않는다.
React 컴포넌트가 다시 렌더링될 때도 마찬가지로, current 속성의 값이 유실되지 않는다.

해당 컴포넌트를 브라우저에서 실행하면 콘솔에 아래와 같은 로그가 찍힌다.

시작 버튼을 누르면 새로운 intervalId가 생성되고, 정지 버튼을 누르면 기존 intervalId가 정리되는 것을 확인할 수 있다.


2. useRef로 DOM에 접근하기

React로 웹 애플리케이션을 개발하다 보면 간혹 React 컴포넌트가 아닌 HTML 엘리먼트에 직접 접근해서, DOM API를 이용하여 제어해야 할 필요가 있다.

ref prop

React의 ref prop은 HTML 엘리먼트의 레퍼런스를 변수에 저장하기 위해서 사용한다.

예를 들어, <input> 엘리먼트에 ref prop으로 inputRef라는 변수를 넘기게 되면, 이 inputRef 객체의 current 속성을 통해서 <input> 엘리먼트에 접근할 수 있고, DOM API를 이용하여 제어할 수 있다.

<input ref = {inputRef}/>

useRef

ref prop에는 React API를 이용해서 생성한 current 속성을 갖는 특정 형태의 객체만을 할당할 수 있다.
클래스 기반 컴포넌트에서는 React.createRef() 함수를,
함수형 컴포넌트에서는 useRef() 훅(hook) 함수를 사용하여 이 객체를 생성할 수 있다.

최근에는 함수형 컴포넌트를 선호하기 때문에 useRef() 훅(hook) 함수를 자주 사용한다.

ex) input 엘리먼트 제어하기

ref prop은 여러 가지 HTML 엘리먼트 중에서도 <input>을 제어할 때 많이 사용된다.

예를 들어, 버튼을 클릭했을 때, 비활성화(disabled)되어 있던 입력란을 활성화시키며 포커스(focus)를 이동시키는 React 컴포넌트를 작성할 수 있다.

useRef() 훅(hook) 함수를 사용하여 inputRef 객체를 생성한 후, <input> 엘리먼트의 ref prop에 넘긴다. 이렇게 하면 inputRef 객체의 current 속성에는 <input> 엘리먼트의 레퍼런스가 저장된다.
따라서 <button> 엘리먼트의 클릭(click) 이벤트 핸들러에서는 inputRef.current로 간단하게 <input> 엘리먼트를 제어할 수 있다.


마찬가지 방법으로 입력란을 원래대로 비활성화 시켜주는 버튼도 쉽게 구현할 수 있다.

결론

HTML 엘리먼트에 직접 접근하는 것은 jQuery 시절에 주로 쓰이던 imperative(명령형) 방식의 웹 프로그래밍이다.
따라서, Declarative(선언형) 프로그래밍 패러다임을 기반으로 하는 React를 포함한 모던 자바스크립트 라이브러리에서는 꼭 필요한 경우가 아니라면 이러한 접근 방식은 지양하는 것이 좋다.

profile
⏰ Good things take time

0개의 댓글