My Boundary As Much As I Experienced

forwardRef란? 그리고 고차 컴포넌트에 대하여. 본문

FrontEnd/React

forwardRef란? 그리고 고차 컴포넌트에 대하여.

Bumang 2024. 5. 28. 18:17

forwardRef란?

챗지피티의 설명에 따르면, '자식 컴포넌트의 DOM 엘리먼트 또는

클래스 인스턴스에 접근할 수 있도록 하는 기능을 제공한다'라고 한다.

 

그런데 그냥 쉽게 말해서 '자식 컴포넌트에 ref를 props로 내려줘야'할 때 써야한다.

 

예를 들어 아래와 같은 경우, ref로 어떤 DOM 요소를 관찰하려고 하는데, 단순 jsx태그가 아니라

컴포넌트인 경우 이렇게 ref를 내려줘야한다.

이때 ref라는 이름으로 내려주면 forwardRef를 써야한다는 경고가 나온다.

 

props의 이름으로 아무거나 임의로 쓸 수 있는거 같지만,

'ref'같은 이름은 예약어로 forwardRef를 쓸때만 사용할 수 있는 것이다.

 

사용법

부모 컴포넌트에서 ref를 만들어서 내려준다. (여기서 그냥 inputRef={inputRef} 식으로 props로 내려주면 forwardRef를 쓰는 의미가 사라진다.)

 

// 부모 컴포넌트
class ParentComponent extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
  }

  componentDidMount() {
    this.inputRef.current.focus();
  }

  render() {
    return <MyInput ref={this.inputRef} />;
  }
}

 

자식 컴포넌트에서:

forwardRef를 import해온 뒤

컴포넌트를 forwardRef()에 두른다.

이때 콜백 함수에 인자를 2개 꺼낼 수 있는데,

(props: 다른 props, ref ) 식으로 ref를 따로 꺼내 쓸 수 있다.

// forwardRef를 불러오기
import React, { forwardRef } from 'react';


// 자식 컴포넌트에 forwardRef()를 둘러준다.
const MyInput = forwardRef((props, ref) => (
  <input ref={ref} {...props} />
));

 

 

굳이 일반 props를 쓰지않고 forwardRef를 쓰는 이유

ref 이름 제약도 없고, 캡슐화가 되어 재사용성이 좋다.

옛날에는 forwardRef가 아니라 일반 props를 아래처럼 썼었다.

 <SomeComponent someRef={someRef} />

 

이렇게 Ref자체를 props이름으로 만들어 내려줘도 별 문제없이 작동하긴 한다.

그러나 이렇게 사용하면 자식 컴포넌트는 이제 'someRef'라는 이름으로만 써야

조작할 수 있는 컴포넌트가 되는 것이다.

 

자식 컴포넌트 내 ref 이름만 제한적이게 되는게 아니라,

해당 이름으로 부모에 useRef를 만들어야하는 것이기 때문에 제약이 조금 많다.

 

forwardRef를 썼을 땐 어디서 이 컴포넌트를 썼든 간에

ref={ ... }에 원하는대로 useRef를 만들어서 연결할 수 있다. 

 

 

의미적으로 다름

props는 본래 '데이터 전달을 위한 목적'의 데이터다.

forwardRef는 하위에 있는 DOM요소를 구독하기 위함에 불과하다.

그러므로 forwardRef를 사용함으로써 의미적인 구분을 하여 코드에 대한 명료함을 올릴 수 있는 것이다.

 

 

 

고차 컴포넌트: 이렇게 컴포넌트를 감싸는 wrapper 함수를 말함

React.memo나 forwardRef도 모두 컴포넌트를 감싸 그 반환값으로 무언가 속성이 추가된? 느낌의 기능이다.

이런 컴포넌트를 wrapper 함수라 한다. 고차 컴포넌트는 또 한 번 기회가 되면 정리하겠다.