본문 바로가기

javascript/react

[React] useRef Hook

리액트는 기본적으로 리액트 내부에서 관리하는 virtual DOM을 갱신하고, 갱신된 내용을 웹사이트, 앱 등 다양한 실제 DOM에 대응시키는 방식으로 동작한다. 그러나, 특정 상황에서는 실제 DOM에 접근하고 싶을 수 있다. 리액트에서는 실제 웹 환경에 존재하는 엘리먼트에 대해 직접적으로 접근할 수 있도록 useRef hook을 제공한다.

const ref = useRef(); // ref의 선언 
...
return (<input ... ref={ref} />); 
// ref와 실제 input 엘리먼트를 ref를 통해 연결

사용법은 극히 간단하다.

  • useRef 을 이용하여 ref 객체를 선언
  • 위에서 생성된 ref 객체를 연결하기를 원하는 태그의 ref 프로퍼티로 전달

위와 같은 방법을 통해 생성된 객체는 실제 DOM 상의 엘리먼트를 가리키게 된다. 이때 맨 처음 렌더링 하기 이전에는 ref 객체는 어떤 엘리먼트도 가리키지 않는다. 첫 렌더링이 수행될 때 ref 프로퍼티를 가진 jsx에게 전달되는 시점에 ref 객체와 실제 엘리먼트가 대응되고, 이 이후부터는 ref 객체가 특정 엘리먼트를 가리키게 된다. 

현재 문서에서 사용되는 예시 파일은 다음 github 주소에 있다.

https://github.com/blaxsior/JS_Study/tree/ex 

 

import { useRef } from 'react';
import styles from './UserCreateForm.module.css';

const UserCreateForm = (props) => {
    const nameRef = useRef();
    const ageRef = useRef();

    console.log(nameRef); // nameRef의 내용이 출력된다.

   ...
}

export default UserCreateForm;

 

 

위 코드에 의하면, current 는 undefined 가 나온다. console.log는 컴포넌트 함수 내에서의 위치 상 실제 렌더링과 관련된 return문보다 앞에 위치하는데, 첫번째 렌더링 이전의 경우 위에서 언급한 것 처럼 아직 ref가 할당된 상태가 아니기 때문에 ref가 가리키는 객체인 current가 undefined 상태인 것을 볼 수 있다. 

 

이후 name 및 age에 적당한 값을 넣고, 이를 add 해보자. 해당 작업이 수행되면 컴포넌트들이 업데이트 되면서 UserCreateForm 역시 업데이트 될 것이다.

 

console.log를 통해 current가 가리키는 대상이 실제로 업데이트 되었으며, 실제 DOM에 존재하는 input을 가리키고 있는 모습을 볼 수 있다.

ref 객체를 통해 접근할 수 있는 current 객체는 위 스크린샷처럼 실제 DOM 상의 엘리먼트를 가리킨다. 따라서 ref 객체를 이용하면 기존 자바스크립트에서 querySelector을 통해 특정 엘리먼트의 프로퍼티를 직접 조정하던 것처럼 엘리먼트를 조정할 수 있다.

 

현재 애플리케이션의 경우 이름을 입력받은 이후, 해당 값을 비워줄 때 current.value에 직접 접근하여 값을 갱신하는데 ref의 프로퍼티를 직접 접근하고 있다.

 

애니메이션의 직접적인 실행, 미디어 재생 관리 등 리액트만으로 처리하기 어려운 경우, useRef 및 ref의 사용이 권장된다. 그러나 이런 부득이한 상황이 아닌 경우, ref은 리액트의 virtual DOM을 이용한 상태 관리에 대한 일관성을 파괴하므로 이를 남용하는 것은 추천되지 않는다. 선언적으로 해결할 수 있는 문제에 대해서는 ref의 사용을 지양하자

'javascript > react' 카테고리의 다른 글

[React] useReducer Hook  (0) 2021.12.14
[React] useEffect Hook  (0) 2021.12.13
[React] Portal  (0) 2021.11.24
[React] useState Hook  (0) 2021.11.22
[React] 컴포넌트  (0) 2021.11.17