ref란?

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

<div id="id_"></div>

이와 같이 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 ref이다.

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

정답은 'DOM'을 직접적으로 꼭 건드려야 할 때 이다.

함수형 컴포넌트에서 ref를 사용하려면 Hooks를 사용해야 하기 때문에 우선 클래스형 컴포넌트부터 시작하자.

1.예제 컴포넌트 생성

// Vaildation.css

.success {
  background-color: lightgreen;
}

.failure {
  background-color: lightcoral;
}
// Vaildation.js

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

class Vaildation 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 Vaildation;

input에서는 onChange 이벤트가 발생하면 handleChange를 호출해 state의 password값을 업데이트하게 한다.
button에서는 onClick이벤트가 발생하면 handleButtonClick을 호출해 clicked값을 참으로 설정했고, vaildated값을 검증 결과로 설정했다.
input의 className값에는 누르기 전에는 비어 있는 문자열을 전달하며, 버튼을 누른 후에는 검증 결과에 따라 success값 또는 failure값을 설정한다.

//App.js

import React from "react";
import Vaildation from "./Vaildation";

const App = () => {
  return <Vaildation />;
};

export default App;

DOM을 꼭 사용해야 하는 상황

가끔 state만으로 해결할 수 없는 기능이 있다.
특정 input에 포커스 주기, 스크롤 박스 조작하기, Canvas요소에 그림 그리기 등
이 때는 어쩔 수 없이 Dom에 직접적으로 접근해야 하는데, 이 때 ref를 사용한다.

콜백함수를 통한 ref 설정

ref를 만드는 가장 기본적인 방법은 콜백 함수를 사용하는 것이다.
ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 된다.
이 콜백 함수는 ref값을 파라미터로 전달받는다.
함수 내부에서 파라미터로 받은 ref를 컴포넌트의 멤버 변수로 설정해준다.

// 콜백함수 사용 예시
<input ref={(ref) => {this.input=ref}} />

d이렇게 하면 앞으로 this.input은 input요소의 DOM을 가리킨다.
ref의 이름은 원하는 것으로 자유롭게 지정할 수 있다.

createRef를 통한 ref설정

ref를 만드는 또 다른 방법은 리액트에 내장되어 있는 createRef라는 함수를 사용하는 것이다.

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

우선 컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아주어야 한다.
그리고 해당 멤버 변수를 ref를 달고자 하는 요소에 ref props로 넣어 주면 설정이 완료된다.
this.input.current를 조회하면 DOM에 접근할 수 있다.

이렇게 진행하면, 버튼을 누르면 input 포커스가 버튼으로 넘어가며
더 이상 input창에 텍스트 커서가 깜빡이지 않는다.

input에 ref 달기

버튼에서 onClick이벤트가 발생할 때 input에 포커스를 주도록 코드를 수정할 수도 있다.

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

class Vaildation 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",
    });
    this.input.focus();
  };
  render() {
    return (
      <div>
        <input
          ref={(ref) => (this.input = ref)}
          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 Vaildation;

버튼을 눌러도 커서의 포커스가 input에 유지되어 있다.

좋은 웹페이지 즐겨찾기