ref, forwardRef, mergeRefs의 이해

오영일·2024년 6월 1일

ReactNative

목록 보기
4/9

목차
1. ref
2. forwardRef
3. mergeRefs
4. node와 ref의 관계
5. 객체형 ref와 함수형 ref
6. mergeRefs를 사용해서 ref를 합쳐야 하는 이유

1. ref

[ 1 ] ref란 무엇인가?
ref는 리액트에서 DOM 노드나 리액트 컴포넌트 인스턴스에 접근할 수 있게 해주는 기능입니다.
이를 통해 컴포넌트의 상태 외부에서 특정 요소에 접근하고 조작할 수 있습니다.

[ 2 ] ref.current란 무엇인가?
ref.current는 ref가 가리키는 실제 DOM 노드나 컴포넌트 인스턴스를 의미합니다.
객체형 ref의 경우, ref.current는 해당 노드나 인스턴스에 접근할 수 있는 속성입니다.

2. forwardRef

forwardRef는 부모 컴포넌트에서 자식 컴포넌트로 ref를 전달할 수 있게 해줍니다. 이를 통해 부모 컴포넌트가 자식 컴포넌트의 DOM 노드나 컴포넌트 인스턴스에 접근할 수 있습니다.

3. mergeRefs

여러 개의 ref를 하나의 노드에 병합하여 할당해야 할 때, mergeRefs 함수를 사용하면 두 개 이상의 ref가 동일한 노드를 가리킬 수 있도록 할 수 있습니다.

import {ForwardedRef} from 'react';

function mergeRefs<T>(...refs: ForwardedRef<T>[]) {
  return (node: T) => {
    refs.forEach(ref => {
      if (typeof ref === 'function') {
        ref(node);
      } else if (ref) {
        ref.current = node;
      }
    });
  };
}

...refs는 여러 개의 ref를 배열로 전달받을 수 있게 해줍니다.

4. node와 ref의 관계

node는 실제 DOM 노드나 리액트 컴포넌트 인스턴스를 의미합니다. 예를 들어,

<div ref={ref} />

의 경우 node는 해당 div가 엘리먼트가 됩니다. ref.current에 node를 할당하면, ref는 해당 노드인 div를 가리키게 됩니다.

5. 객체형 ref와 함수형 ref

[ 1 ] 객체형 ref
객체형 ref는 useRef 훅을 사용하여 생성됩니다.
ref.current 속성을 통해 DOM 노드나 컴포넌트 인스턴스에 접근할 수 있습니다.

const ref = useRef(null);
useEffect(() => {
  console.log(ref.current); // 해당 노드나 인스턴스에 접근
}, []);
<div ref={ref}>Hello</div>

[ 2 ] 함수형 ref
함수형 ref는 useRef 대신 콜백 함수를 사용하여 정의됩니다.
함수형 ref는 ref.current를 사용하지 않고, 함수가 호출될 때 인자로 전달된 노드를 처리합니다.

const ref = node => {
  if (node) {
    console.log(node); // 해당 노드나 인스턴스에 접근
  }
};
<div ref={ref}>Hello</div>

함수형 ref는 node를 인수로 받는 함수로, 이 함수는 해당 컴포넌트가 마운트될 때 호출됩니다.
이 함수형 ref는 current 속성이 없기 때문에 직접적으로 current 속성에 접근할 수 없습니다.
대신 함수가 호출될 때마다 해당 노드를 처리하여 원하는 작업을 수행합니다.

6. mergeRefs를 사용해서 ref를 합쳐야 하는 이유

mergeRefs를 사용하면 함수형 ref와 객체형 ref를 병합하여, 동일한 노드에 접근할 수 있습니다. 이를 통해 부모 컴포넌트와 자식 컴포넌트 모두에서 동일한 노드에 접근할 수 있게 됩니다.

import React, { useRef, forwardRef } from 'react';
import { mergeRefs } from './mergeRefs';

const InputField = forwardRef((props, ref) => {
  const localRef = useRef(null);

  return (
    <input
      ref={mergeRefs(localRef, ref)} // mergeRefs를 통해 두 개의 ref를 병합
      {...props}
    />
  );
});

const ParentComponent = () => {
  const parentRef = useRef(null);

  return <InputField ref={parentRef} />;
};

export default ParentComponent;

위의 예시에서 mergeRefs를 사용하여 localRef와 parentRef를 병합합니다. 이렇게 하면 InputField 컴포넌트 내부의 localRef와 부모 컴포넌트에서 전달된 parentRef 모두가 동일한 input 노드를 가리키게 됩니다.

profile
ISurrender

0개의 댓글