[리액트를 다루는 기술 5장] ref: DOM에 이름 달기

H Kim·2023년 12월 3일
0

기술 책 읽기

목록 보기
9/20
post-thumbnail
post-custom-banner

5.1 ref는 어떤 상황에 사용해야 할까?


  • ref
    리액트 프로젝트 내부에서 DOM에 이름을 다는 방법
  • 리액트 컴포넌트 안에서도 id를 사용할 수 있지만 id는 전역적인 것이다. 그러나 ref는 컴포넌트 내부에서만 작동하기 때문에 중복되는 일 없이 사용할 수 있다.

  • ref는 DOM을 꼭 직접적으로 건드려야 할 때만 사용해야 한다.


DOM을 꼭 사용해야 하는 상황

- 특정 input에 포커스 주기
- 스크롤 박스 조작하기
- Canvas 요소에 그림 그리기

5.2 ref 사용


  • 콜백 함수를 통한 ref 설정
<input ref={(ref) => {this.input = ref}} />

ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해준다. 이 콜백 함수는 ref 값을 파라미터로 전달받는다. 그리고 함수 내부에서 파라키ㅓ로 받은 ref를 컴포넌트의 멤버 변수로 설정해 준다.

이렇게 하면 앞으로 this.input은 input 요소의 DOM을 가르키게 된다. ref의 이름은 원하는 것으로 자유롭게 지정가능하다. this.superman = ref 처럼 마음대로도 가능하다.


  • createRef를 통한 ref 설정

리액트 내장함수인 createRef를 사용할 수 있다.
이 기능은 리액트 v16.3부터 도입되었다.

import { Component } from 'react';

class RafSample extends Component {
  input = React.createRef();

  handleFocus = () => {
    this.input.current.focus();
  };

  render() {
    return (
      <div>
        <input ref={this.input} />
      </div>
    );
  }
}

export default RefSample;

5.3 컴포넌트에 ref 달기


컴포넌트 내부에 있는 DOM을 컴포너느 외부에서 사용할 때 컴포넌트 자체에 ref를 달 수 있다.

<MyComponent ref={(ref) => this.myComponent = ref} />

import React, { Component } from "react";
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;

문법상으로는 onClick={this.scrollBox.scrollToBottom} 같은 형식으로 작성해도 틀리지 않으나 처음 컴포넌트가 렌더링 될 때는 this.scrollBox 값이 undefined임으로 에러가 난다. 따라서 화살표 함수 문법을 사용하여 아예 새로운 함수를 만들고 그 내부에서 this.scrollBox.scrollToBottom 메서드를 실행하면 버튼을 누를 때(이미 한 번 렌더링을 해서 this.scrollBox를 설정한 시점) this.scrollBox.scrollToBottom 값을 읽어와서 실행하므로 오류가 발생하지 않는다.


import React, { Component } from "react";

class ScrollBox extends Component {
  scrollToBottom = () => {
    const { scrollHeight, clientHeight } = this.box;
    this.box.scrollTop = scrollHeight - clientHeight;
  };

  render() {
    const style = {
      border: "1px solid black",
      height: "300px",
      width: "300px",
      overflow: "auto",
      position: "relative",
    };

    const innerStyle = {
      width: "100%",
      height: "650px",
      background: "linear-gradient(white, black)",
    };

    return (
      <div
        style={style}
        ref={(ref) => {
          this.box = ref;
        }}
      >
        <div style={innerStyle} />
      </div>
    );
  }
}

export default ScrollBox;

5.4 정리


  • ref를 사용하지 않고도 원하는 기능을 구현할 수 있는지 반드시 고려한 후에 활용해야 한다.

  • 서로 다른 컴포넌트끼리 데이터를 교류할 때 ref를 사용하는 것은 잘못된 방식이다. 이것은 리액트 사상에 어긋난 설계이기 때문이다. 컴포넌트끼리 데이터를 교류할 때는 언제나 데이터를 부모 <-> 자식의 흐름으로 교류해야 한다.

  • 함수 컴포넌트에서 ref 함수의 사용은 useRef 라는 Hook 함수를 통해 사용한다.


post-custom-banner

0개의 댓글