본문 바로가기
React

[리액트] ref로 리액트의 돔요소 가져오기

by 메이플 🍁 2022. 4. 7.

⚠️ 이 포스팅은 김민준님의 리액트를 다루는 기술 스파르타코딩클럽 리액트 기초반을 공부하고 정리한 블로그 포스팅입니다. ⚠️

 

포스팅에 해당하는 목차는 다음과 같습니다:

리액트를 다루는 기술: 5장 ref: DOM에 이름 달기, 8장 Hooks

  • 5.1 ref는 어떤 상황에서 사용해야 할까?
  • 5.2 ref 사용
  • 5.3 컴포넌트에 ref 달기
  • 5.4 정리
  • 8.6 useRef

 

리액트 기초반

  • 2-10 Ref! 리액트에서 돔요소를 가져오려면?

 


 

1. ref란?

HTML 웹사이트에서 DOM 요소를 가져와 작업하고 싶을때는 id를 붙여 접근한 후 CSS에서 특정 스타일을 적용하거나 JavaScript로  getElementById와 같은 DOM Selector 함수를 사용해서 DOM을 선택한다. HTML에서 DOM 요소에 접근하기 위해 id를 붙여주었다면 리액트에서는 DOM 요소에 접근하기 위해 ref를 붙여준다.

HTML

<div id="root"></div>

React

<div ref={변수}></div>

1.2 왜 리액트에서는 DOM요소에 id를 붙여주는 대신 ref를 사용할까?

리액트에서 컴포넌트는 재사용할 수 있는 작은 블럭이다. 만약 같은 컴포넌트가 재사용 되는 경우 id가 컴포넌트가 불려진 횟수만큼 사용된다. 알다시피 id는 딱 한번만 쓸 수 있는 고유한값이다. id와 달리 ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동하기 때문에 이런 문제가 발생하지 않는다. 

1.3 ref를 사용해야하는 상황

리액트에서 DOM에 직접 접근해 변환을 주어야할 때만 ref를 사용하고 일반적으로 DOM에 상태가 변화될때는 state를 사용한다.

다음과 같은 경우에는 state가 아닌 ref를 부여해 리액트에서 DOM에 직접 접근해 변환을 주어야한다:

  1. 포커스, 텍스트 선택영역, 혹은 미디어의 재생을 관리할 때
  2. 애니메이션을 직접적으로 실행시킬 때
  3. 서드 파티 DOM 라이브러리를 React와 같이 사용할 때

 

2. ref사용법

2.1 클래스형 컴포넌트

  • 클래스형 컴포넌트에서 ref 사용하기: React.createRef()
  • 멤버 변수 input에 React.createRef()를 할당한다
  • 멤버 변수를 가리킬때 this.input으로 접근한다
  • 접근시 this.input.current로 조회한다
  • input 요소에 ref={this.input}이 들어가져 있으므로 this.input.current는 input요소의DOM을 가리키게 된다
import React from "react";

class BucketListClass extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      bucketlists: ["영화관 가기", "매일 책읽기", "수영 배우기"]
    };

    // ref 생성
    this.input = React.createRef();
  }

  InputValueUpdate = () => {
    this.setState({
      bucketlists: this.state.bucketlists.concat(this.input.current.value)
    });
    this.input.current.value = "";
  };

  // componentDidMount는 컴포넌트가 모두 렌덜링이 된 후 실행되는 메서드다
  // 여기서 this.input.current는 input DOM을 가리킨다
  componentDidMount() {
    console.log(this.input.current);
  }

  render() {
    return (
      <>
        <div>
          <h1>내 버킷리스트</h1>
          <hr />
          <ul>
            {this.state.bucketlists.map((bucketlist, index) => (
              <li key={index}>{bucketlist}</li>
            ))}
          </ul>
        </div>
        <div>
          {/* input요소에 ref 연결 */}
          <input type="text" ref={this.input} />
          <button onClick={this.InputValueUpdate}>추가하기</button>
        </div>
      </>
    );
  }
}

export default BucketListClass;

2.2 함수형 컴포넌트

  • 함수형 컴포넌트에서 ref 사용하기: useRef
  • useRef는 ref를 쉽게 사용할 수 있도록 해주는 Hook
  • useRef를 사용하여 ref를 설정하면 useRef를 통해 만든 객체 안의 current 값이 실제 엘리먼트를 가리킨다
import React, { useRef, useState } from "react";

const App = () => {
  const [bucketlists, setBucketlists] = useState([
    "영화관 가기",
    "매일 책읽기",
    "수영 배우기"
  ]);

  // useRef hook으로 ref 생성
  const inputValue = useRef();

  // setTimeout으로 시간지연을 준 후에 inputValue 값 테스트하기
  // inputValue.current가 input DOM을 가리킨다
  window.setTimeout(() => {
    console.log(inputValue);
    console.log(inputValue.current);
  }, 1000);

  const onClick = () => {
    setBucketlists(bucketlists.concat(inputValue.current.value));
    inputValue.current.value = "";
  };

  return (
    <>
      <div>
        <div>
          <h1>내 버킷리스트</h1>
          <hr />
          <ul>
            {bucketlists.map((bucketlist, index) => (
              <li key={index}>{bucketlist}</li>
            ))}
          </ul>
        </div>
        <div>
          {/* input요소에 ref 연결 */}
          <input type="text" ref={inputValue} />
          <button onClick={onClick}>추가하기</button>
        </div>
      </div>
    </>
  );
};

export default App;

useRef의 두가지 역할

1. 특정 태그를 가리키고 싶을때

<input ref={inputEl}></input>
inputEl.current.focus();

2. 컴포넌트 리렌더링을 일으키지 않는 값을 지정하고 싶을때 (state는 값이 업데이트 될때마다 컴포넌트가 리렌더링이 된다)

const num = useRef(0)
num ++

댓글