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

최정윤·2023년 5월 15일
0

코낭

목록 보기
16/41

5. ref: DOM에 이름 달기

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

▶ DOM 요소의 id

<div id="my-element"></div>
  • 특정 DOM요소에 어떤 작업을 해야 할 때 요소에 id를 달면 CSS에서 특정 id에 특정 스타일을 적용하거나 자바스크립트에서 해당 id를 가진 요소를 찾아서 작업할 수 있다.
  • HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼 리액트 프로젝트 내부에서 ref를 활용하여 DOM에 이름을 달 수 있다.

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

  • 특정 DOM에 작업을 해야 할 때 ref를 사용해야 한다.
  • ref는 DOM을 꼭 직접적으로 건드려야 할 때 사용한다.
    ▶ HTML 예제 코드
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>Example</title>
        <style>
            .success {
                background-color: green;
            }

            .failure {
                background-color: red;
            }
        </style>
        <script>
            function validate() {
                var input = document.getElementById('password');
                input.className = '';
                if(input.value === '0000') {
                    input.className = 'success';
                } else {
                    input.className = 'failure';
                }
            }
        </script>
    </head>
    <body>
        <input type="password" id="password"/>
        <button onclick="validate()">Validate</button>
    </body>
</html>
  • 순수 자바스크립트로 만든 웹 사이트에서 input을 검증할 때는 다음과 같이 특정 id를 가진 input에 클래스를 설정해준다.
  • 비밀번호가 0000으로 맞았을 때는 초록색 배경색으로 틀렸을 때는 빨간색 배경으로 표시된다.


  • 리액트에서 id와 같은 작업은 굳이 DOM에 접근하지 않아도 state로 구현할 수 있다.

5.1.1 예제 컴포넌트 생성

▶ 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;
  • input에서는 onChange 이벤트가 발생하면 handleChange를 호출하여 state의 password값을 업데이트하게 된다.
  • button에서는 onclick 이벤트가 발생하면 handleButtonClick을 호출하여 clicked 값을 참으로 설정했고, validation 값을 검증 결과로 설정한다.
  • input의 className값은 버튼을 누르기 전에는 비어 있는 문자열을 전달하며, 버튼을 누른 후에는 검증 결과에 따라 success 값 또는 failure 값을 설정한다. 값에 따라 input 색상이 초록색 또는 빨간색으로 나타난다.

5.1.2 App 컴포넌트에서 예제 컴포넌트 렌더링

▶ App.js

import { Component } from 'react';
import ValidationSample from './ValidationSample';

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

export default App;

5.1.3 DOM을 꼭 사용해야 하는 상황

  • 가끔 state 만으로 해결할 수 없는 기능이 있다. -> 이 경우 ref를 사용한다.
    • 특정 input에 포커스 주기
    • 스크롤 박스 조작하기
    • Canvas 요소에 그림 그리기 등

5.2 ref 사용

5.2.1 콜백 함수를 통한 ref 설정

  • ref를 만드는 가장 기본적인 방법은 콜백 함수를 사용하는 것이다.
  • ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 된다.

▶ 콜백함수 사용 예시

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

5.2.2 createRef를 통한 ref 설정

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

▶ createRef 사용 예시

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;
  • createRef를 사용하여 ref를 만들려면 우선 컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아 주어야 한다.
  • 변수를 ref를 달고자 하는 요소에 ref props로 넣어 주면 ref 설정이 완료된다.
  • 설정한 뒤 나중에 ref를 설정해 준 DOM에 접근하려면 this.input.current를 조회하면 된다.
  • 콜백 함수를 사용할 때와 다른 점은 이렇게 뒷부분에 .current를 넣어 주어야 한다는 것이다.

5.2.3 적용

  • 버튼을 한 번 눌렀을 때, 포커스가 다시 input 쪽으로 자동으로 넘어가도록 코드를 작성해보자.

5.2.3.1 input에 ref 달기

▶ ValidationSample.js의 input요소

(...)
	<input
		ref={(ref) => this.input=ref}
        (...)
	/>
  • input 요소에 ref를 달아준다.

5.2.3.2 버튼 onClick 이벤트 코드 수정

  • 버튼에서 onClick 이벤트가 발생할 때 input에 포커스를 주도록 코드를 수정
    ▶ ValidationSample.js - handleButtonClick 메서드
    handleButtonClick = () => {
        this.setState({
            clicked: true,
            validated: this.state.password === '0000'
        });
        this.input.focus();
    }
  • 위와 같이 수정하면 버튼 클릭시 포커스가 input으로 바로 넘어오게 된다.

5.3 컴포넌트에 ref 달기

  • 리액트에서는 컴포넌트에도 ref를 달 수 있다.
  • 컴포넌트 내부에 있는 DOM을 컴포넌트 외부에서 사용할 때 쓴다.
  • 컴포넌트에 ref를 다는 방법은 DOM에 ref를 다는 방법과 똑같다.

5.3.1 사용법

<MyComponenet
	ref={(ref) => {this.myComponent=ref}}
/>
  • 위와 같이 하면 MyComponent 내부의 메서드 및 멤버 변수에도 접근할 수 있다.
    • 내부의 ref에도 접근할 수 있다.
  • 스크롤 박스가 있는 컴포넌트를 하나 만들고, 스크롤바를 아래로 내리는 작업을 부모 컴포넌트에서 실행해 보자.

5.3.2 컴포넌트 초기 설정

  • JSX의 인라인 스타일링 문법으로 스크롤 박스를 만들고 최상위 DOM에 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;

5.3.2.2 App 컴포넌트에서 스크롤 박스 컴포넌트 렌더링

▶ App.js

import { Component } from 'react';
import ScrollBox from './ScrollBox';

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

export default App;

profile
개발 기록장

0개의 댓글