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

Jake_Young·2020년 8월 20일
0
post-thumbnail

🤣 ref란?

  • HTML에서 id를 사용하는 상황에서 사용하는 react의 개념
  • 그렇다면 리액트에서는 왜 id를 사용하지 않는가?
  • 사용할 수는 있지만, 권장하지는 않는다.
  • id는 전체 HTML에서 유일해야하는데, ref는 컴포넌트 내부에서만 작동하기 때문에 안전하다.
  • 특별한 라이브러리에서 id를 사용해야하는 상황이 생길 때가 아니라면 사용을 권장하지 않는다.

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

DOM을 꼭 직접적으로 건드려야 할 때

ref가 필요한 구체적인 예

1. 특정 input에 포커스 주기
2. 스크롤 박스 조작하기
3. Canvas 요소에 그림 그리기 등

ref를 사용하는 두 가지 방법

콜백 함수를 통한 ref 설정

  • ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 된다.
  • 이 콜백 함수는 ref 값을 파라미터로 전달 받는다.
  • 그리고 함수 내부에서 파라미터로 받은 ref를 컴포넌트의 멤버 변수로 설정해 준다.
  • 그 예시는 다음과 같다. <input ref={(ref)=>{this.input=ref}} />
  • 이렇게 하면 앞으로 this.input은 input 요소의 DOM을 가리킨다.
  • ref의 이름은 원하는 것으로 자유롭게 지정할 수 있다.
  • DOM 타입과 관계없이 this.superman = ref처럼 마음대로 지정합니다.

createRef를 통한 ref 설정

  • ref를 만드는 또 다른 방법은 리액트에 내장되어 있는 createRef라는 함수를 사용하는 것입니다.
  • 리액트 v16.3 이후 버전에서만 작동한다.
  • 그 예시는 다음과 같다.
import React, { Component } from "react";

export default class RefSample extends Component {
  input = React.createRef();

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

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

State만 적용하여 css를 변환한 예제

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

export default class ValidationSample extends Component {
  state = {
    password: "",
    clicked: false,
    validates: false
  };

  handleChange = (e) => {
    this.setState({ password: e.target.value });
  };

  handleButtonClick = () => {
    this.setState({
      clicked: true,
      validated: this.state.password === "0000"
    });
  };

  render() {
    return (
      <div>
        <h1>ref 연습</h1>

        <input
          type="password"
          value={this.state.password}
          onChange={this.handleChange}
          className={
            this.state.clicked
              ? this.state.validated
                ? "success"
                : "failure"
              : ""
          }
        />
        <button onClick={this.handleButtonClick}>검증하기</button>
      </div>
    );
  }
}

😄 컴포넌트에 ref 달기

app.js 파일

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

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

scrollBox 파일

import React, { Component } from "react";

export default 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>
      </div>
    );
  }
}

🎁 scrollTop, scrollHeight, clientHeight의 차이

scrollTop: 세로 스크롤바 위치 (0~350, scrollHeight - clientHeight)

scrollHeight: 스크롤이 있는 박스 안의 div 높이 (650)

clientHeight: 스크롤이 있는 박스의 높이 (300)

profile
자바스크립트와 파이썬 그리고 컴퓨터와 네트워크

0개의 댓글