
Refs는 React에서 DOM 요소나 컴포넌트 인스턴스에 직접적으로 접근할 수 있게 해 줍니다. 일반적으로, React 데이터 흐름 (props를 통해 부모에서 자식으로 데이터를 전달) 외의 방법을 제공합니다.
import { forwardRef, useImperativeHandle, useRef } from 'react';
import { createPortal } from 'react-dom';
const Modal = forwardRef((props, ref) => {
const dialog = useRef();
useImperativeHandle(ref, () => ({
open() {
dialog.current.showModal();
}
}));
return createPortal(
<dialog ref={dialog}>{props.children}
<form method="dialog">
<button>{props.buttonCaption}</button>
</form>
</dialog>,
document.getElementById("modal-root")
);
});
export default Modal;
const Modal = forwardRef((props, ref) => {
const dialog = useRef();
<dialog> HTML 엘리먼트를 참조합니다. useImperativeHandle(ref, () => ({
open() {
dialog.current.showModal();
}
}));
<dialog> 엘리먼트의 showModal 메서드를 호출합니다. return createPortal(
<dialog ref={dialog}>{props.children}
<form method="dialog">
<button>{props.buttonCaption}</button>
</form>
</dialog>,
document.getElementById("modal-root")
);
});
export default Modal;
import { useRef } from 'react';
import Modal from './Modal';
export default function NewProject() {
const modalRef = useRef();
//useRef: modalRef를 통해 Modal 컴포넌트의 인스턴스를 참조합니다.
const handleSave = () => {
// 입력 검증 로직 후
if (/* 유효하지 않은 경우 */) {
modalRef.current.open();
}
};
return (
<>
<Modal ref={modalRef} buttonCaption="OK">
<h2>Invalid Input</h2>
</Modal>
<div>
{/* 폼 입력 필드들 */}
<button onClick={handleSave}>Save</button>
</div>
</>
);
}
모달과 같은 컴포넌트는 보통 사용자의 상호작용(예: 버튼 클릭)에 의해 동적으로 표시되거나 숨겨져야 합니다. React에서 컴포넌트 외부에서 컴포넌트 내부의 메서드(예: 모달 열기)에 접근할 수 있도록 하려면 ref와 forwardRef를 사용하는 것이 효과적입니다.
직접적인 DOM 제어: React에서 직접적인 DOM 조작은 권장되지 않지만, 모달과 같이 복잡한 UI 컨트롤에서는 필수적일 수 있습니다. forwardRef와 useImperativeHandle을 사용하면, React의 선언적 UI 흐름을 벗어나 필요한 경우에만 직접적인 DOM 접근이 가능합니다.
재사용성 및 캡슐화: Modal 컴포넌트는 재사용 가능하며, 그 내부 구현은 외부에 노출되지 않습니다. 다만, 필요한 기능 (open)만을 제공하여 다른 컴포넌트에서 쉽게 사용할 수 있습니다.