Magic Modallatest
API reference

useMagicModal

Close the current stack entry from its own component and return typed data.

useMagicModal<T = void>(): {
  hide(data: T): void;
}

useMagicModal is the close API for a component rendered by magicModal.show. Its context binds hide to the exact stack entry that rendered the component, so it does not need a modal ID.

Modal content only

Call this hook from a component rendered by magicModal.show. Outside that provider, hide is a silent no-op; it cannot discover or close a global stack entry.

Complete typed flow

import { Pressable, Text, View } from "react-native";
import { MagicModalHideReason, magicModal, useMagicModal } from "magic-modal";

type Confirmation = {
  approved: boolean;
};

function ConfirmationModal() {
  const { hide } = useMagicModal<Confirmation>();

  return (
    <View>
      <Text accessibilityRole="header">Publish this release?</Text>

      <Pressable
        accessibilityRole="button"
        onPress={() => hide({ approved: true })}
      >
        <Text>Publish</Text>
      </Pressable>

      <Pressable
        accessibilityRole="button"
        onPress={() => hide({ approved: false })}
      >
        <Text>Keep editing</Text>
      </Pressable>
    </View>
  );
}

export async function requestPublishApproval() {
  const result = await magicModal.show<Confirmation>(ConfirmationModal, {
    accessibilityLabel: "Confirm release publication",
  });

  if (result.reason === MagicModalHideReason.INTENTIONAL_HIDE) {
    return result.data.approved;
  }

  console.info("Publish confirmation dismissed:", result.reason);
  return false;
}

Pass the same return type to useMagicModal<T>() and show<T>(). TypeScript checks the value sent to hide, while the reason check narrows the awaited result before data is read.

Backdrop press, swipe, Android Back, web Escape, and hideAll() resolve the promise with their own reason and no data. Use try/catch for errors from the async work that follows the modal result.

Hook or imperative API

SituationAPI
The current modal closes itselfuseMagicModal<T>().hide(data)
Application code opens a modal and waits for its resultawait magicModal.show<T>(component)
Code outside the modal closes one known entrymagicModal.hide(data, { modalID })
A logout or reset boundary clears the stackmagicModal.hideAll()

For a modal that returns no data:

const { hide } = useMagicModal();

<Button title="Done" onPress={() => hide()} />;

hide always creates an INTENTIONAL_HIDE result. Backdrop, back-button, swipe, and global cleanup results are produced by their respective close paths.

Read hide results for the complete result union and every dismissal reason.

On this page