Frontend/React
[React] ref를 prop으로 넘기기 - forwardRef()
개발하는루루
2023. 4. 28. 21:10
우선, ref는 React에서 DOM에 직접 접근하기 위해 사용한다.
사용방법은 우선 useRef hook을 선언하여 ref 객체를 생성한 다음 원하는 Element의 ref 값을 넘기면 된다.
import { useRef } from 'react';
export default fuction App() {
const inputRef = useRef(null);
const focusHandler = () => {
inputRef.current.disabled = false;
inputRef.current.focus();
};
const resetHandler = () => {
inputRef.current.disabled = true;
inputRef.current.value = "";
};
return <Input type="text" ref={inputRef} disabled />
이렇게 되면 InputRef 객체의 current 속성에 <input> element의 래퍼런스가 저장된다.
그리고 inputRef 객체를 통해 input element를 제어할 수 있다.
이렇게 ref prop은 HTML Element 접근이라는 특수한 용도로 사용되기 때문에, 일반적인 prop으로 사용할 수 없다.
아래와 같은 상황을 생각해보자.
주로 Tab이나 Modal을 만들 때 외부에서 ref를 정의하여 <Tab />이나 <Modal />에 props로 넘겨주어야 될 일이 많다.
흔한 서비스 중 하나로, useOnClickOutside 함수를 적용할 때를 예시로 들어보자.
// useOnClickOutside.ts
import { useEffect, useRef } from 'react';
export const useOutsideClick = (callback: any) => {
const ref = useRef<any>();
useEffect(() => {
const handleClick = (event: any) => {
if (ref.current && !ref.current.contains(event.target)) {
callback();
}
};
document.addEventListener('click', handleClick);
return () => {
document.removeEventListener('click', handleClick);
};
}, [callback]);
return ref;
};
// Detail.tsx
export default function Detail() {
const [openModal, setOpenModal] = useState<boolean>(false);
const modalRef = useOutsideClick(() => {
if (openModal) {
setOpenModal(false);
}
});
return <>
isDetailModalOpen && <Modal ref={modalRef} />
</>
}
Modal.tsx가 따로 정의되어있는 상태에서 prop로 ref를 그냥 넘기면
Type '{ ref: MutableRefObject<any>; }' is not assignable to type 'IntrinsicAttributes & ForwardedRef<HTMLDivElement>'.
Property 'ref' does not exist on type 'IntrinsicAttributes & ForwardedRef<HTMLDivElement>'.ts(2322)
위와 같은 아래가 뜬다.
ref를 props로 넘기려면 ref를 넘기려는 React component를 forwardRef()로 감싸주면 함수는 ref라는 매개변수를 갖게 되는데 그 매개변수에 prop을 넘길 수 있다.
그래서, Modal이라는 React component를 아래와 같이 수정해 주면 된다.
import { ForwardedRef, forwardRef} from 'react';
export default forwardRef(function Modal(
_,
ref: ForwardedRef<HTMLDivElement>
) {
return (
<div />
);
});