ref:DOM에 이름 달기

정다윤·2023년 1월 27일
0

React

목록 보기
5/12
post-thumbnail

일반 HTML에서 DOM 요소에 이름을 달때는 id를 사용합니다.

DOM 요소의 id

<div id="my-element></div>

이렇게 HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 ref(reference) 개념입니다.

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

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

클래스형 컴포넌트에서 ref를 사용하는 방법을 알아보겠습니다.
1. ValidationSample 컴포넌트 만들기
2. input에 ref달기
3. 버튼을 누를 때마다 input에 포커스 주기

예제 컴포넌트 생성

src 디렉터리 안에 ValidationSample.css와 ValidationSample.js파일을 만듭니다.

ValidationSample.css

.success {
  background-color: lightgreen;
}
.failure {
  background-color: lightcoral;
}

ValidationSample.js

import { Component } from "react";
import "./ValidationSample.css";

class ValidationSample extends Component {
  state = {
    password: "",
    clicked: false,
    validated: false,
  };

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

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

  render() {
    return (
      <div>
        <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>
    );
  }
}

export default ValidationSample;

콜백 함수를 통한 ref 설정

ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해주면 됩니다.

콜백 함수 사용 예시

<input ref={(ref)=>{this.input=ref}}

createRef를 통한 ref 설정

리액트 v16.3부터 도입된 createRef함수를 사용할 수 있습니다.

createdRef 사용 예시

import {Component} from 'react';

class RefSample extends Component{
	input = React.createRef();
    
    handleFocus = () => {
    	this.input.current.focus();
    }
    
    render(){
    	return(
        	<div>
            	<input ref={this.input}/>
            </div>
        )
    }
    export default RefSample;
}

컴포넌트에 ref 달기

컴포넌트 내부에 있는 DOM을 컴포넌트 외부에서 사용할 때 씁니다.

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

이렇게 하면 MyComponent 내부의 메서드 및 멤버 변수에도 접근할 수 있습니다.

  1. ScrollBox 컴포넌트 만들기
  2. 컴포넌트에 ref 달기
  3. ref를 이용하여 컴포넌트 내부 메서드 호출하기

ScrollBox.js

import { Component } from "react";

class ScrollBox extends Component {
  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;

컴포넌트에 메서드 생성

  • scrollTop : 세로 스크롤바 위치(0~350)
  • scrollHeight : 스크롤이 있는 박스 안의 div 높이(650)
  • clientHeight : 스크롤이 있는 박스의 높이(300)

ScrollBox.js

import { 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;

컴포넌트에 ref달고 내부 메서드 사용

App.js

import { 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;

리액트를 다루는 기술 [개정판] (김민준, 길벗출판사) 책을 참고하였습니다.

0개의 댓글