공부블로그

리액트 5장. ref: DOM에 이름 달기 본문

리액트/리액트를 다루는 기술

리액트 5장. ref: DOM에 이름 달기

떠어영 2021. 1. 5. 18:20
<div id="my-element"></div>

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

이를 통해 css에서 특정 id에 스타일을 적용하거나, 자바스크립트에서 해당 id요소를 찾아 작업할 수 있다.

이와 비슷하게 리액트에서 DOM에 이름을 다는 방법이 바로 ref 이다.

 

우선 state를 사용한 예제를 작성해보자.

 

App. js

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

class App extends Component {
  render() {
    return <ValidationSample />;
  }
}

export default App;

 

 

 ValidationSample. css

.success {
  background-color: lightgreen;
}

.failure {
  background-color: lightcoral;
}

 

ValidationSample. js

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

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

  handleChange = (e) => {
    this.setState({
      password: e.target.value, //입력을 password로 업데이트
    });
  };

  handleButtonClick = () => {
    this.setState({
      clicked: true, //클릭됨
      validated: this.state.password === "0000", //코드 확인
    });
  };

  render() {
    return (
      <div>
        <input
          type="password"
          value={this.state.password}
          onChange={this.handleChange}
          className={
            //css에서 className으로 접근
            this.state.clicked //클릭되면 아래줄 실행, 아니면 비어있는 문자열 전달
              ? this.state.validated //유효하면 success, 아니면 failure가 className으로 설정
                ? "success"
                : "failure"
              : ""
          }
        />
        <button onClick={this.handleButtonClick}>검증하기</button>
      </div>
    );
  }
}
export default ValidationSample;

위와 같이 state와 className을 이용해 기능을 구현할 수도 있지만 

  • 특정 input에 포커스 주기

  • 스크롤 박스 조작하기

  • Canvas 요소에 그림 그리기 등

'DOM을 꼭 직접적으로 건드려야 할 때' 는 ref를 사용한다!

 

5. 1 ) ref 사용하기

5. 1. 1 ) 콜백 함수 를 통한 ref 설정 :  ref라는 콜백 함수를 props로 전달.

< input ref= {(ref) => {this.input=ref}} /> //this.input은 input 요소의 DOM을 가리킨다.

 이 콜백함수는 함수 내부에서 파라미터로 전달받은 ref값을 컴포넌트의 멤버 변수로 설정해준다.

 

 

5. 1. 2 ) 위에서 작성한 ValidationSample에서 버튼을 눌러도 포커스가 다시 input에 가도록 코드를 작성해보자.

 

ValidationSample. js의  handliButtonClick 메서드

handleButtonClick = () => {
    this.setState({
      clicked: true, //클릭됨
      validated: this.state.password === "0000", //코드 확인
    });
    this.input.focus(); //포커스를 input에
  };

 

ValidationSample. js의 input요소

<input
	ref={(ref) => (this.input = ref)}
	//콜백함수로 ref 달아줌 -> 이제 this.input이 컴포넌트 내부의 input요소를 가리키게 됨
	...
/>

 

 

 

5. 1. 3 ) createRef 함수를 통한 ref 설정 

import React, {Component} from 'react';

class Refsample extends Component {
	input = React.createRef(); //createRef함수로 생성한 ref를 input이라는 멤버변수로 담아준다.
    
	handleFocus = ()=> {
    	this.input.current.focus(); //ref를 설정한 DOM에 접근
    }
    
   render() {
		return (
        	<div>
            	<input ref={this.input} /> //(ref라는)props에 생성한 ref를 넣어준다.
            </div>
        );
     }
}
export default RefSample;

 

 

5. 2 ) 컴포넌트에 ref 달기

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

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

이렇게 하면 MyComponent 내부의 메서드, 멤버 변수, ref 에도 접근할 수 있다. (ex: myComponent. handleClick...) 

 

 

5. 2. 1 )  스크롤박스가 있는 컴포넌트를 만들고, 버튼을 누르면 스크롤바를 맨아래로 내리는 코드를 작성해보자.

 

Scrollbox. js

import React, { Component } from "react";

class Scrollbox extends Component {
  scrollToBottom = () => {
    //스크롤바를 맨 아래로 내리는 메서드
    const { scrollHeight, clientHeight } = this.box;
    /* 비구조화 할당 문법
     const scrollHeight = this.box.scrollHeight : 스크롤이 있는 박스안의 div 높이
     const clientHeight = this.box.clientHeight : 스크롤이 있는 박스의 높이
    */
    this.box.scrollTop = clientHeight - scrollHeight;
  }; //scrollTop: 세로 스크롤바 위치 

  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} //이 요소의 스타일은 style
        ref={(ref) => {
          //이 요소는 이제 this.box를 통해 접근 가능
          this.box = ref;
        }}
      >
        <div style={innerStyle} />
      </div>
    );
  }
}
export default Scrollbox;

위에서 비구조화 할당을 하는 이유....? 

scrollTop, scrollHeight, clientHeight는 리액트에서 제공하는 것...?

 

App. js 

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

class App extends Component {
  render() {
    return (
      <div>
        <Scrollbox ref={(ref) => (this.scrollbox = ref)} />
         // 컴포넌트에 ref 달기 
        <button onClick={() => this.scrollbox.scrollToBottom()}>
         // this.scrollbox를 통해 Scrollbox에 접근하고 배부 메서드 사용 
          맨밑으로
        </button>
      </div>
    );
  }
}

export default App;

 

이렇게 이번 장에서는 DOM요소 (와 컴포넌트) 에 이름을 달아주는 ref에 대해 알아보았다.

기본적인 사용법에는 1. 콜백함수 이용 (ref라는 콜백함수를 props로 전달) : ref = { ( ref ) => { this.이름=ref } }

                                       2. createRef 함수 : input = React.createRef ( );  이 있다.

 

ref는 컴포넌트 내부에서 DOM요소에 직접 접근해야 할 때만 사용해야 한다!