목차
1. ref
2. forwardRef
3. mergeRefs
4. node와 ref의 관계
5. 객체형 ref와 함수형 ref
6. mergeRefs를 사용해서 ref를 합쳐야 하는 이유
[ 1 ] ref란 무엇인가?
ref는 리액트에서 DOM 노드나 리액트 컴포넌트 인스턴스에 접근할 수 있게 해주는 기능입니다.
이를 통해 컴포넌트의 상태 외부에서 특정 요소에 접근하고 조작할 수 있습니다.
[ 2 ] ref.current란 무엇인가?
ref.current는 ref가 가리키는 실제 DOM 노드나 컴포넌트 인스턴스를 의미합니다.
객체형 ref의 경우, ref.current는 해당 노드나 인스턴스에 접근할 수 있는 속성입니다.
forwardRef는 부모 컴포넌트에서 자식 컴포넌트로 ref를 전달할 수 있게 해줍니다. 이를 통해 부모 컴포넌트가 자식 컴포넌트의 DOM 노드나 컴포넌트 인스턴스에 접근할 수 있습니다.
여러 개의 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를 배열로 전달받을 수 있게 해줍니다.
node는 실제 DOM 노드나 리액트 컴포넌트 인스턴스를 의미합니다. 예를 들어,
<div ref={ref} />
의 경우 node는 해당 div가 엘리먼트가 됩니다. ref.current에 node를 할당하면, ref는 해당 노드인 div를 가리키게 됩니다.
[ 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 속성에 접근할 수 없습니다.
대신 함수가 호출될 때마다 해당 노드를 처리하여 원하는 작업을 수행합니다.
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 노드를 가리키게 됩니다.