[React] Ref 와 DOM

Juhyang·2022년 2월 28일
0

TypeScript + React

목록 보기
5/5

Ref를 사용하는 이유

DOM에 직접 접근할때.

예시: <div id="user"></div> 로 id를 주어서,
기존에 document.getelementbyid() 등을 사용해서 직접 해당 DOM 요소에 접근하였다.
이렇듯 html에서는 Id를 붙였다면, React 에서는 ref를 사용한다.

Ref를 사용해야하는 상황

  1. React에서 State로만 해결할 수 없고, DOM을 반드시 직접 건드려야 할 때 사용한다.

    • input에 focus 주기
    • Canvas 요소에 그림 그리기
    • 애니메이션 직접적인 실행
    • 스크롤박스에서의 특정한 이벤트 처리 등....
  2. 컴포넌트를 렌더링 시키지 않고, dom에만 접근하여 내가 원하는 효과를 주고싶을때

    • ref는 state와 다르게 값이 변경된다고 해서 컴포넌트가 렌더링 되지 않는다.
    • 그래서 주로 focus나 text를 선택할때 많이 사용된다.

실무에서는 어쩔수 없이 사용할 때를 제외하고 웬만해선 ref를 지양하는편이다.
이유는 DOM 조작 이벤트 자체가 무겁고, React 자체가 최대한 DOM을 조작안하려고 가상돔을 쓰기 때문이다.

함수형 컴포넌트 - useRef

예시) dom-to-image 라는 특정 영역을 png로 저장하는 라이브러리를 사용하기위해
원하는 요소에 ref를 부여하고 사용하는 코드

import { useRef } from 'react';
import domtoimage from 'dom-to-image'

const TestComponent = (props) => {

    const {id, nickName} = props;
    const personInfo = useRef(); // 1. personInfo에 useRef 객체 생성

    // 영역을 png로 저장하는 함수
    const onClick = function () {
        domtoimage.toPng(personInfo.current) // 3. ref를 부착한 요소에 .current로 접근 
        .then(function (blob) {
          window.saveAs(blob, 'user-card.png');
        })
    };

    return (
        <div>
            <div className="box" ref={personInfo}> // 2. div.box 요소에 위에서 생성한 ref 부착.
      
                <p> {id} - {nickName} 테스트 영역 </p>
            </div>
            <button onClick={onClick}>저장</button>
        </div>
    );
}

클래스형 컴포넌트 - React.createRef

아래 코드는 버튼을 누르면 input text에 포커스를 주는 코드이다.
클래스형은 ref를 달고자 하는 요소에 ref라는 콜백 함수를 전달하면 된다.

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    // textInput DOM 엘리먼트를 저장하기 위한 ref를 생성
    this.textInput = React.createRef();
    this.focusTextInput = this.focusTextInput.bind(this);
  }

  focusTextInput() {
    // DOM API를 사용하여 명시적으로 text 타입의 input 엘리먼트를 포커싱
    // current을 사용해서 프로퍼티에 접근, focus로 포커싱
    this.textInput.current.focus();
  }

  render() {
    // React에게 우리가 text 타입의 input 엘리먼트를
    // 우리가 생성자에서 생성한 `textInput` ref와 연결하고 싶다고 이야기합니다.
    return (
      <div>
        <input
          type="text"
      	//ref 콜백함수로 부착
          ref={(ref) => (this.textInput = ref)} /> 
		 
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput}
        />
      </div>
    );
  }
}

클래스형 컴포넌트 - 컴포넌트에 ref 달기

이 방법은, 컴포넌트 내부의 DOM 요소를 컴포넌트 외부에서 사용해야 할 때 활용한다.

import React, { Component } from "react";
import "./App.css";
import ScrollBox from "./ScrollBox";

class App extends Component {
  render() {
    return (
      <div>
        <ScrollBox ref={(ref) => (this.scrollBox = ref)} />
        <button onClick={() => this.scrollBox.ScrollToBottom()}>맨 밑으로</button>
      </div>
    );
  }
}

export default App;

여기서 <button onClick={this.scrollBox.ScrollToBottom()}> 로 쓰게되면,
컴포넌트가 처음 렌더링 될때 scrollBox 컴포넌트에 ref가 달리기 전이므로, undefined.ScrollToBottom() 을 실행하여 오류가 난다.
그러므로 화살표 함수를 만들면 버튼을 누를때 실행되므로, 이미 button을 누를때는 ref 가 붙어있는 상황이기 때문에 오류가 발생하지 않는다.

profile
kurly - commerce web development

0개의 댓글