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

devHagaa·2022년 6월 22일
post-thumbnail

이 포스팅은 김민준님의 '리액트를 다루는 기술'을 요약한 글입니다.

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

리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 바로 ref(reference의 줄임말) 개념입니다.

ref는 전역적으로 작동하지 않고 컴포넌트 내부에만 작동하기 떄문에 중복 id를 가진 DOM이 여러개 일 걱정이 없습니다.


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

ref는 DOM을 꼭 직접 건드려야 할 때 사용합니다.

하지만 리액트에선 DOM에 접근하지 않아도 state로 구현 가능합니다.

DOM을 꼭 사용해야 하는 상황?
- 특정 input에 포커스 주기
- 스크롤 박스 조작하기
- Canvas 요소에 그림 그리기 등


5.2 ref 사용

5.2.1 콜백 함수를 통한 ref 설정

ref를 만들기: 콜백 함수 사용 ← ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달. 이 콜백 함수는 ref 값을 파라미터로 전달 받아 컴포넌트의 멤버 변수로 설정

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

this.input은 input 요소의 DOM을 가리킴

5.2.2 createRef를 통한 ref 설정

리액트에 내장되어 있는 createRef 함수 사용

5.2.3 적용

jsx
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 = (e) => {
        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 ? 'sucess' : 'failure') : ''}                    
                />
                <button onClick={this.handleButtonClick}>검증하기</button>
            </div>
        );
    }    
}

export default ValidationSample;

5.3 컴포넌트에 ref 달기

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

5.3.1 사용법

<MyComponent  // MyComponent 내부 메서드 및 멤버 변수에도 접근 가능
    ref={(ref) => {this.myComponent=ref}}
/>

5.3.2 컴포넌트 초기 설정

// 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;
// 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()}   /* 처음 렌더링 될 때 this.scrollBox는 undefined 이므로 함수화 해서 넣어주기 */>
          맨 밑으로
        </button>
      </div>
    );
  }
}

export default App;

5.4 정리

컴포넌트 내부에서 DOM에 직접 접근식 ref 사용.

다른 컴포넌트끼리 데이터 교류시는 ref 사용 X = 컴포넌트끼리 데이터 교류시 부모 ↔ 자식 으로 교류 = 리덕스 등..

profile
디자이너인가 퍼블리셔인가 프론트엔드개발자인가 정체성의 혼란을 겪는 개린이

0개의 댓글