문서보기가이드Hooks

Hooks

overlay-kit은 오버레이 상태를 전역에서 관리할 수 있도록 useCurrentOverlay, useOverlayData 훅을 제공해요.

useCurrentOverlayuseOverlayData를 활용하면 오버레이 외부에서도 상태 기반 UX 제어, 포커싱, 조건적 렌더링 등을 더욱 유연하게 구현할 수 있어요.


useCurrentOverlay

현재 가장 위에 떠 있는 오버레이의 ID를 반환해요.

오버레이의 ID는 오버레이를 열 때 overlay.open() 또는 overlay.openAsync()의 두 번째 인자로 다음처럼 overlayId를 넘겨 직접 지정할 수 있어요:

overlay.open(
  ({ isOpen, close }) => <ConfirmDialog isOpen={isOpen} close={close} />,
  { overlayId: 'custom-overlayId' }
);

만약 overlayId를 생략하면 내부에서 랜덤으로 overlay-kit-[랜덤숫자]로 ID가 생성돼요.

이 ID를 기반으로 특정 오버레이가 열렸는지 조건을 분기하거나 포커스/단축키 제어 등에 활용할 수 있어요.


오버레이 A와 B를 설정하여 각 오버레이를 열었을 때 useCurrentOverlay의 값이 어떻게 변하는지 살펴볼게요.


import { OverlayProvider, overlay, useCurrentOverlay } from 'overlay-kit';
import Button from '@mui/material/Button';
import Typography from '@mui/material/Typography';
import { ConfirmDialog } from './confirm-dialog';

function App() {
  const current = useCurrentOverlay();

  return (
    <div>
      <Button
        variant="contained"
        onClick={() => {
          overlay.open(({ isOpen, close }) => {
            return (
              <ConfirmDialog
                isOpen={isOpen}
                close={close}
                title="오버레이 A"
              />
            );
          }, { overlayId: 'modal-a' });
        }}
      >
        오버레이 A 열기
      </Button>

      <Button
        variant="outlined"
        style={{ marginLeft: '8px' }}
        onClick={() => {
          overlay.open(({ isOpen, close }) => {
            return (
              <ConfirmDialog
                isOpen={isOpen}
                close={close}
                title="오버레이 B"
              />
            );
          }, { overlayId: 'modal-b' });
        }}
      >
        오버레이 B 열기
      </Button>

      <Typography variant="body1" style={{ marginTop: '5px' }}>
        현재 current 값: {current}
      </Typography>
    </div>
  );
}

export const Example = () => {
  return (
    <OverlayProvider>
      <App />
    </OverlayProvider>
  );
};


useOverlayData

현재 메모리에 존재하는 모든 오버레이 상태 정보를 반환해요.

열린 오버레이뿐만 아니라 닫혔지만 메모리에 남아 있는 오버레이도 포함돼요.

각 오버레이 항목은 다음과 같은 속성으로 구성되어 있어요:

속성명타입설명
idstring오버레이를 식별하는 고유 ID예요. overlay.open()overlayId로 지정하거나, 생략 시 자동으로 생성돼요.
componentKeystring내부적으로 사용하는 고유 키로, 오버레이 UI를 React가 올바르게 렌더링하고 구분하는 데 사용돼요. 매번 열릴 때마다 새 값이 할당돼요.
isOpenboolean현재 오버레이가 열려 있는지 여부를 나타내요. close()를 호출하면 false가 되고, unmount()되기 전까지는 메모리에 남아 있어요.
controllerFC오버레이를 실제로 렌더링하는 React 컴포넌트예요. overlay.open() 시 넘겨준 함수 형태의 UI가 이 필드에 저장돼요.

예를 들어, 다음처럼 확인할 수 있어요:

const overlayData = useOverlayData();
 
Object.entries(overlayData).forEach(([id, item]) => {
  console.log(id);               // overlayId
  console.log(item.isOpen);     // true / false
  console.log(item.controller); // 컴포넌트 렌더링 함수
});

각각의 오버레이를 closeunmount 방식으로 닫았을 때, useOverlayData에 남아 있는 오버레이 정보가 어떻게 달라지는지 살펴볼게요.


import { OverlayProvider, overlay, useOverlayData } from 'overlay-kit';
import Button from '@mui/material/Button';
import Stack from '@mui/material/Stack';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import Typography from '@mui/material/Typography';
import { ConfirmDialog } from './confirm-dialog';

function App() {
  const overlayData = useOverlayData();

  const allOverlayIds = Object.keys(overlayData);
  const openOverlayIds = allOverlayIds.filter(
  (id) => overlayData[id].isOpen
  );

  return (
    <div>
      <Stack direction="row" spacing={1}>
        <Button
          variant="contained"
          onClick={() => {
            overlay.open(({ isOpen, close }) => {
              return (
                <ConfirmDialog
                isOpen={isOpen}
                close={close}
                title="오버레이 A (close)"
                />
              );
            }, { overlayId: 'modal-close' });
          }}
        >
          오버레이 A 열기 (close)
        </Button>

        <Button
          variant="outlined"
          style={{ marginLeft: '8px' }}
          onClick={() => {
            overlay.open(({ isOpen, unmount }) => {
              return (
                <ConfirmDialog
                  isOpen={isOpen}
                  close={unmount}
                  title="오버레이 B (unmount)"
                />
              );
            }, { overlayId: 'modal-unmount' });
          }}
        >
        오버레이 B 열기 (unmount)
        </Button>
      </Stack>
      <div style={{ marginTop: '24px' }}>
      <Typography variant="subtitle1">열려 있는 오버레이</Typography>
      <List dense>
        {openOverlayIds.length > 0 ? (
          openOverlayIds.map((id) => <ListItem key={id}>{id}</ListItem>)
        ) : (
          <ListItem>없음</ListItem>
        )}
      </List>

      <Typography variant="subtitle1" style={{ marginTop: '16px' }}>
        메모리에 남아 있는 오버레이
      </Typography>
      <List dense>
        {allOverlayIds.length > 0 ? (
          allOverlayIds.map((id) => <ListItem key={id}>{id}</ListItem>)
        ) : (
          <ListItem>없음</ListItem>
        )}
      </List>
      </div>
    </div>
  );
}

export const Example = () => {
  return (
    <OverlayProvider>
      <App />
    </OverlayProvider>
  );
};