상세 컨텐츠

본문 제목

[리액트 스타터 1] 5장. ref

22-23/22-23 리액트 스타터 1

by 2jo 2022. 11. 5. 10:00

본문

728x90


5장 ref: DOM에 이름달기

public/index.html 파일의 div 태그의 idroot로 설정되어 있습니다. 이처럼 id를 사용하면 특정 DOM 요소에 대하여 쉽게 접근하여 처리할 수 있습니다. 이렇게 HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼, 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법 ref(reference)입니다.

<!--public/index.html 파일-->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
  </body>
</html>

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

refDOM을 직접적으로 건드려야 할 때 사용해야 합니다. 예로 클래스형 컴포넌트에서 ref를 사용하는 방법을 알아봅시다.

 

5.1.1 예제 컴포넌트 생성

src 디렉터리 안에 ValidationSample.cssValidationSample.js 파일을 생성해봅시다.

/*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
        });
    };
    
    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 함수를 호출합니다. handleChange 함수는 statepassword 값을 업데이트합니다. className 값은 버튼을 누르기 전에는 비어 있는 문자열을 전달하며, 버튼이 눌린 후에는 검증 결과에 따라 success 또는 failure으로 설정합니다. 그리고 ValidationSample.css에 의하여 success일 땐 input 색상이 초록색으로, failure일 땐 input 색상이 빨간색으로 나타납니다.

button에서 onClick 이벤트가 발생하면 handleButtonClick 함수를 호출합니다. handleButtonClick 함수는 clicked 값을 true로 설정하고, validated 값을 검증 결과로 설정합니다.

 

 

 

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

App 컴포넌트에서 ValidationSample 컴포넌트를 렌더링 해봅시다.를 보다 잘 사용하기 위해 이번 예제에서 App 컴포넌트는 함수 컴포넌트에서 클래스형 컴포넌트로 전환합니다.

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

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

export default App;

 

 

 

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

위 예제에서 state를 사용하여 필요한 기능을 구현하였습니다. 그러나 이 방법으로는 특정 input에 포커스 주기, 스크롤 박스 조작하기, Canvas 요소에 그림 그리기 등 DOM에 직접적으로 접근하는 상황을 처리하기 어렵습니다. DOM에 직접 접근하기 위해 ref를 사용합니다.


5.2 ref 사용

ref를 사용하는 방법은 두 가지입니다.

 

 

 

5.2.1 콜백 함수를 통한 ref 설정

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

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

이 코드에서 this.inputinput 요소의 DOM을 가리킵니다.의 이름은 원하는 것으로 설정할 수 있습니다.

 

 

 

5.2.2 createRef를 통한 ref 설정

리액트에 내장된 createRef 함수를 사용하여 ref를 만드는 방법도 있습니다. 리액트 v16.3부터 도입되어 보다 더 적은 코드로 사용 가능합니다.

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;

createRef 함수를 사용하여 ref를 만들려면 컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아야 합니다. 그리고 해당 멤버 변수를 ref를 달고자 하는 요소에 ref props로 넣으면 ref 설정이 됩니다. 이후 접근 시 this.input.current를 조회하면 됩니다. 콜백 함수와 다르게 뒷부분에 . current를 넣어야 합니다.

 

 

 

5.2.3 적용

앞서 작성한 ValidationSample 컴포넌트에 콜백 함수를 사용하여 ref를 달아봅시다..

//ValidationSample.js의 input 요소

<input
    ref={(ref) => this.input = ref} //ref 달기
    type="password"
    value={this.state.password}
    onChange={this.handleChange}
    className={this.state.clicked ? this.state.validated ? 'success' : 'failure' : ''}
/>
//ValidationSample.js의 handleButtonClick 메서드

handleButtonClick = () => {
        this.setState({
        clicked: true,
        validated: this.state.password === '0000'
        });
    this.input.focus(); //ref를 통한 접근
};

this.input이 컴포넌트 내부의 input 요소를 가리키고 있으므로 일반 DOM을 다루듯이 작성하면 됩니다.


5.3 컴포넌트에 ref 달기

리액트에서는 컴포넌트에도 ref를 달 수 있는데, 컴포넌트에서 오류가 나지 않게 하는 화살표 함수 문법을 활용하여 메서드를 만들어 봅시다.

 

 

 

5.3.1 사용법

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

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

 

 

 

5.3.2 컴포넌트 초기 설정

ScrollBox 컴포넌트 파일을 생성합니다. JSX 인라인 스타일링 문법으로 스크롤 박스를 만들고 최상위 DOMref를 달아봅시다.

 

 

 

5.3.2.1 컴포넌트 파일 생성

import React, { 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 컴포넌트에서 ScrollBox 컴포넌트를 렌더링 해봅시다.

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

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

export default App;

 

 

 

5.3.3 컴포넌트에 메서드 생성

컴포넌트에 스크롤바를 맨 아래로 내리는 메서드를 만들어봅시다. 자바스크립트로 스크롤바를 내릴 때 DOM 노드가 가진 다음 값을 사용합니다.

더보기

scrollTop: 세로 스크롤바 위치

scrollHeight: 스크롤이 있는 박스 안의 div 높이

clientHeight: 스크롤이 있는 박스의 높이

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>
        );
    }
}

scrollToBottom 메서드는 부모인 App 컴포넌트에서 ScrollBoxref를 달면 사용할 수 있습니다.

 

 

 

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

App 컴포넌트에서 ScrollBox 컴포넌트에 ref를 달고, 버튼을 누르면 scrollToBottom 메서드를 실행하도록 렌더링 해봅시다.

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

컴포넌트가 처음 렌더링 될 때에는 this.scrollBox 값이 정의되어 있지 않으므로 onClick 값으로 바로 불러온다면 오류가 발생합니다. 따라서 화살표 함수 문법을 사용하여 새로운 함수를 만들고 그 내부에서 this.scrollBox. scrollToBottom 메서드를 실행하는 것이 안전합니다.


Quiz

1. 태그에 (________) 선택자를 적용하면 특정 요소에 쉽게 접근할 수 있다.

2. 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법을 (________)이라고 한다.

3. refDOM(________)할 때 사용한다.

4. DOM에 직접 접근하는 상황 중 하나는 (________) 조작하기가 있다.

5. ref를 만드는 가장 기본적인 방법은 (________)를 사용하는 것이다.

6. 리액트에 내장된 (________) 함수를 사용하면 ref를 만들 수 있다.

7. 컴포넌트의 안전한 처리를 위하여 ref는 주로 (________)를 활용하여 메서드를 작성한다.

8. Corner 컴포넌트가 작성되어 있을 때, App 컴포넌트에서 Corner 컴포넌트 내부의 CornerReact1 메서드를 실행하는 구문을 작성하라.

9. 본문의 예제 ScrollBoxcreateRef 함수를 이용하여 ref를 달아라.


Corner React1

Editor: 동동

728x90

관련글 더보기