상세 컨텐츠

본문 제목

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

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

by 케이비이 2022. 11. 5. 10:00

본문

728x90

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

HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 있습니다. 바로 ref(reference의 줄임말) 개념입니다

5.1.1 예제 컴포넌트 생성

//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 (
            <>
                <input
                    type="password"
                    value={this.state.password}
                    onChange={this.handleChange}
                    className={this.state.clicked ? (this.state.validated ? 'success' : 'failure') : ''}
                />
                <button onClick={this.handleButtonClick}>검증</button>
            </>
        )
    }
}

export default ValidationSample

input에서는 onChange 이벤트가 발생하면 handleChange를 호출하여 state의 password 값을 업데이트하게 했습니다. button에서는 onClick 이벤트가 발생하면 handleButtonClick을 호출하여 clicked 값을 참으로 설정했고, validated 값을 검증 결과로 설정했습니다.

input의 className 값은 버튼을 누르기 전에는 비어 있는 문자열을 전달하며, 버튼을 누른 후에는 검증 결과에 따라 success 값 또는 failure 값을 설정합니다. 그리고 이 값에 따라 input 색상이 초록색 또는 빨간색으로 나타납니다.

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

App 컴포넌트에서 ValidationSample 컴포넌트를 불러와 렌더링해 보겠습니다.

//App.js
import React, { 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 사용

ref의 사용은 두가지로 콜백 함수와 createRef를 통한 ref 설정입니다.

5.2.1 콜백 함수를 통한 ref 설정

ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주면 됩니다. 이 콜백 함수는 ref 값을 파라미터로 전달받습니다. 그리고 함수 내부에서 파라미터로 받은 ref를 컴포넌트의 멤버 변수로 설정해 줍니다.

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

5.2.2 createRef를 통한 ref 설정

리액트에 내장되어 있는 createRef라는 함수를 사용합니다.

import React, { Component } from ‘react‘;
<input ref={(ref) => {this.input=ref}} />

class RefSample extends Component {  
input = React.createRef();

handleFocus = () => {  
this.input.current.focus();  
}

render() {  
return (

);  
}  
}

export default RefSample;

createRef를 사용하여 ref를 만들려면 우선 컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아 주어야 합니다. 그리고 해당 멤버 변수를 ref를 달고자 하는 요소에 ref props로 넣어 주면 ref 설정이 완료됩니다.
설정한 뒤 나중에 ref를 설정해 준 DOM에 접근하려면 this.input.current를 조회하면 됩니다.

5.2.3 적용

5.2.3.1 input에 ref 달기

//ValidationSample.js의 input 요소
(…)
        <input
          ref={(ref) => this.input=ref}
          (…)
        />

5.2.3.2 버튼 onClick 이벤트 코드 수정

//ValidationSample.js - handleButtonClick 메서드
handleButtonClick = () => {
  this.setState({
    clicked: true,
    validated: this.state.password === '0000'
  });
  this.input.focus();
}

코드를 수정하기 전에는 버튼을 누르면 텍스트 커서의 깜빡임이 더 이상 보이지 않았습니다. 수정 후에는 버튼을 눌러도 포커스가 input에 있는 점을 확일할 수 있습니다.

5.3 컴포넌트에 ref 달기

5.3.1 사용법

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

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

5.3.2 컴포넌트 초기 설정

5.3.2.1 컴포넌트 파일 생성

//ScrollBox.js
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.js
import React, { Component } from 'react';
import ScrollBox from './ScrollBox';


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

export default App;

5.3.3 컴포넌트에 메서드 생성

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

  • scrollTop: 세로 스크롤바 위치(0~350)
  • scrollHeight: 스크롤이 있는 박스 안의 div 높이(650)
  • clientHeight: 스크롤이 있는 박스의 높이(300)

스크롤바를 맨 아래쪽으로 내리려면 scrollHeight에서 clientHeight 높이를 빼면 됩니다.

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

class ScrollBox extends Component {

  scrollToBottom = () => {
    const { scrollHeight, clientHeight } = this.box;
    /* 앞 코드에는 비구조화 할당 문법을 사용했습니다.
       다음 코드와 같은 의미입니다.
       const scrollHeight = this.box.scrollHeight;
       const clientHeight = this.box.cliengHeight;
    */
    this.box.scrollTop = scrollHeight - clientHeight;
  }

  render() {
    (...)
}

export default ScrollBox;

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

//app.js
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;

코스 수정 이전에는 '맨밑으로' 버튼이 없었습니다.
수정 후에는 '맨밑으로' 버튼을 생성해 주면서 버튼을 누르면 스크롤바를 맨 아래쪽으로 이동할 수 있습니다.

 


Quiz

1. 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법 (     )이다.

2. 리액트는 DOM에 접근하지 않아도 (       )로 구현할 수 있다.

3. state의 사용만으로 해결할 수 없는 기능은 (      )를 사용한다.

4. ref를 만드는 가장 기본적인 방법으로 ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달해 주는 방식은 (      )이다.

5. ref를 사용하는 다른 방법으로 리액트에 내장되어 있는 (         )를 사용한다.

6. 리액트에서는 (       )에도 ref를 달 수 있다.

7. (          )는 스크롤이 있는 박스의 높이를 나타낸다.

8. '5.1.1 예제 컴포넌트 생성'의 ValidationSample.js에 ref를 적용해본다.

9. '5.3.3 컴포넌트에 메서드 생성'의 ScrollBox.js에 ref를 적용해본다.


Corner React3

Editor: 케이비

728x90

관련글 더보기