본문 바로가기
Frontend/ReactJS(완)

React - 5장 : ref. DOM에 이름 달기

by 리키이 2023. 2. 9.

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

- 요소에 id를 달면 css에서 특정 스타일을 적용하거나 자바스크립트로 해당 요소에 작업을 할 수 있다.

 

5-1. ref(reference)

- HTML에서 id를 사용하여 DOM에 이름을 다는 것처럼 리액트 프로젝트 내부에서 DOM에 이름을 다는 방법이 있다.

- 리액트 컴포넌트에 id를 사용하는 것은 권장하지 않는다.
- 컴포넌트는 여러 번 사용할 수 있는데 id는 유니크한 값이기 때문에 잘못된 사용이 될 수 있다.
- ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동하기 떄문에 문제가 발생하지 않는다.

 

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

- DOM을 꼭 직접적으로 건드려야 할 때 사용한다.

  - 특정 input에 포커스 주기

  - 스크롤 박스 조작하기

  - Canvas 요소에 그림 그리기

- 함수형 컴포넌트에서 ref를 사용하려면 Hooks를 사용해야한다.

 

5-2. ref 사용

1) 콜백 함수를 통한 ref 설정

- ref를 만드는 가장 기본적인 방법은 콜백 함수를 사용하는 것이다.

 

ref를 달고자 하는 요소에 ref라는 콜백 함수를 props로 전달한다.
이 콜백 함수는 ref 값을 파라미터로 전달받는다.
함수 내부에서 파라미터로 받은 ref는 컴포넌트의 멤버 변수로 설정해준다.
<input ref={(ref) => {this.input=ref}} />

 

 

2) createRef를 통한 ref 설정

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

- 리액트  v16.3부터 도입이 되었고 이전버전에서는 작동하지 않는다.

- 컴포넌트 내부에서 멤버 변수로 React.createRef()를 담아 주어야 한다.

- 해당 멤버 변수를 ref를 달고자 하는 요소에 ref props로 넣어 주면  ref 설정이 완료된다.

- ref 설정해 준 DOM에 접근하려면 this.input.current를 조회하면 된다.

 

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;

 

5-3. 컴포넌트에 ref 달기

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

- 밑에 코드를 보면 MyComponent 내부의 메서드 및 멤버 변수에도 접근할 수 있다.

- ex) myComponent.handleClick, mycomponent.input

 

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

 

1) 컴포넌트 내부 메서드 사용해보기 

- 문법상으로 onClick = {this.scrollBox.scrollToBottom} 같은 형식으로 작성해도 틀린 것은 아니지만

  컴포넌트가 처음 렌더링될 때는 this.scrollBox값이 undefined이므로 컴포넌트가 처음 렌더링 될 때 this.scrollBox 

  값이 undefined이므로 위의 값을 읽어오는 과정에서 오류가 발생할 수 있다.
  화살표 함수를 통해서 새로운 함수를 만들기 때문에 버튼을 클릭했을 때 this.scrollBox.scrollBottom 값을 읽어와서

  실행하므로 오류가 발생하지 않는다.

 

<ScrollBox.js>

scrollToBottom = () => {
    const { scrollHeight, clientHeight } = this.box;
    /* 앞 코드에는 비구조화 할당 문법이고 다음 코드와 같은 의미이다.
       const scrollHeight = this.box.scrollHeight;
       const clientHeight = this.box.cliengHeight;
    */
    this.box.scrollTop = scrollHeight - clientHeight;
  };
  
  
  
<App.js>

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

class App extends Component {
  render() {
    return (
      <div>
        <ScrollBox ref={(ref) => (this.scrollBox = ref)} />
        <button onClick={() => this.scrollBox.scrollToBottom()}>맨 밑으로</button>
      </div>
    );
  }
}

export default App;

 

5-4. 정리

- 컴포넌트 내부에서 DOM에 직접 접근해야 할 때는 ref를 사용한다.

- 컴포넌트끼리 데이터를 교류할 때는 언제나 데이터를 부모 ↔ 자식 흐름으로 교류해야 한다. 왜냐하면 서로 다른

  컴포넌트끼리 데이터를 교류할 때 ref를 사용한다면 물론 할 수 있겠지만 앱 규모가 커지면 마치 스파게티처럼 구조가

  꼬여 버려서 유지보수 하기에 힘들어진다.

- 리덕스 혹은 Context API를 사용해서 효율적으로 교류할 수 있다.

'Frontend > ReactJS(완)' 카테고리의 다른 글

React - 7장 : 컴포넌트의 Lifecycle Method  (0) 2023.02.14
React - 6장 : 컴포넌트 반복  (0) 2023.02.13
React - 4장 : 이벤트 핸들링  (0) 2023.02.08
React - 3장 : 컴포넌트  (0) 2023.02.06
React - 2장 : JSX  (0) 2023.02.02

댓글