221130 항해99 24일차 ref

요니링 컴터 공부즁·2022년 11월 30일
0

리액트에서는 DOM 요소에 접근하기 위해 주로 ref를 쓴다. document.getElementsByClassName 등을 쓰는 게 아니라 ref를 쓰는 이유는 무엇일까?

  • React로 웹 애플리케이션을 개발하다보면, 간혹 React 컴포넌트가 아닌 HTML 엘리먼트에 직접 접근해서 DOM API를 이용해 제어할 필요가 있다. 이럴 때 React의 독특한 속성인 ref를 사용할 수 있다.

  • 리액트는 실제 DOM이 아니라 가상 DOM을 사용하기 때문에 실제 DOM에 접근하는 document.getElementByClassName 등을 사용하면 에러가 발생한다. 따라서 직접 접근하지 않고 가상 DOM 자체에서 DOM 요소에 접근할 수 있는 ref를 사용한다.

Ref를 사용해야하는 상황
1) React에서 State으로만 해결할 수 없고, DOM을 반드시 직접 건드려야할 때

  • input에 focus 주기

  • Canvas 요소에 그림 그리기

  • 직접적인 애니메이션 실행

  • 서드 파티 DOM 라이브러리를 React와 같이 사용할 때

  • 스크롤박스에서의 특정한 이벤트 처리 등
    2) 컴포넌트를 렌더링 시키지 않고, DOM에만 접근해 원하는 효과를 주고자할 때

  • ref는 state와 다르게 값이 변경된다고 해서 컴포넌트를 리렌더링 시키지 않는다.

  • 그래서 주로 focus나 text를 선택할때 많이 사용된다.

  • React의 ref 속성은 HTML element의 레퍼런스를 변수에 저장하기 위해서 사용한다.

  • 예를 들어, 다음과 같이 input 엘리먼트에 ref 속성으로 inputRef라는 변수를 넘기게 되면, 우리는 이 inputRef 객체의 current 속성을 통해 input 엘리먼트에 접근할 수 있고, DOM API를 이용해 제어할 수 있게 된다.

<input ref={inputRef} />
  • ref 속성에는 React API를 이용해 생성한 current 속성을 갖는 특정 형태의 객체만을 할당할 수 있다. 클래스 기반 컴포넌트에서는 React.createRef() 함수를, 함수형 컴포넌트에서는 useRef() 훅(Hook) 함수를 사용해 이 객체를 생성할 수 있다.

ex1) input 엘리먼트 제어

  • ref prop은 여러가지 HTML 엘리먼트 중에서도 input을 제어할 때 많이 사용된다.
  • 예를 들어, 버튼을 클릭했을 때, 비활성화(disabled)되어 있던 입력란을 활성화시키며 포커스(focus)를 이동시키는 React 컴포넌트는 다음과 같이 작성한다.
  • useRef() 훅(hook) 함수를 사용하여 inputRef 객체를 생성한 후, input 엘리먼트의 ref prop에 넘기고 있다. 이렇게 해주면 inputRef 객체의 current 속성에는 input 엘리먼트의 레퍼런스가 저장된다. 따라서 button 엘리먼트의 클릭(click) 이벤트 핸들러에서는 inputRef.current로 간단하게 input 엘리먼트를 제어할 수 있다.
import React, { useRef } from "react";

function Field() {
  const inputRef = useRef(null);

  function handleFocus() {
    inputRef.current.disabled = false;
    inputRef.current.focus();
  }
// 입력란을 원래대로 비활성화 시켜주는 버튼도 어렵지 않게 추가로 구현할 수 있다.
  function handleReset() {
    inputRef.current.disabled = true;
    inputRef.current.value = "";
  }

  return (
    <>
      <input disabled type="text" ref={inputRef} />
      <button onClick={handleFocus}>활성화</button>
      <button onClick={handleReset}>초기화</button>
    </>
  );
}

ex2) audio 엘리먼트 제어

  • 음악 파일의 재생하거나 중지할 수 있는 컴포넌트를 작성할 수 있다.
  • useRef() 훅(hook) 함수로 audioRef 객체를 생성한 후, audio 엘리먼트의 ref prop에 설정했다. 따라서, 이벤트 핸들러 함수 내에서는 audioRef.current를 통해 audio 엘리먼트의 play()와 pause() 함수를 호출할 수 있다.
import React, { useRef } from "react";
import music from "./music.mp3";

function Player() {
  const audioRef = useRef(null);

  const handlePlay = () => {
    audioRef.current.play();
  };

  const handlePause = () => {
    audioRef.current.pause();
  };

  return (
    <>
      <figure>
        <figcaption>Eyes on You (Sting) - Network 415:</figcaption>
        <audio src={music} ref={audioRef}>
          Your browser does not support the
          <code>audio</code> element.
        </audio>
      </figure>
      <button onClick={handlePlay}>재생</button>
      <button onClick={handlePause}>중지</button>
    </>
  );
}
  • ref prop 관련해서 한 가지 주의할 점은 HTML 엘리먼트에 직접 제어하는 것은 JQuery 시절에 주로 쓰이던 imperative(명령형) 방식의 웹 프로그래밍이라는 것이다. Declarative(선언형) 프로그래밍 패러다임을 기반으로 하는 React를 포함한 모던 자바스크립트 라이브러리에서는 반드시 필요한 경우가 아니라면 이러한 접근 방식은 지양하는 것이 좋다.
  • 실무에서는 어쩔 수 없을 때를 제외하고는 ref 사용을 지양하는 편이다. DOM 조작 이벤트 자체가 무겁고, React 역시 최대한 DOM 조작을 피하기 위해 가상 DOM을 사용하기 때문이다.

참조:
Ref를 사용하는 이유
항해99 3주차 리액트 입문 전 알아야 할 기본 개념
Ref와 DOM
[React] ref로 HTML 엘리먼트에 접근/제어하기

0개의 댓글