A lightweight React hook that enables native back button support for modals and dialogs. Press the back button to close modals instead of navigating away.
npm install react-modal-back-buttonbash
npm install react-modal-back-button
`
`bash
yarn add react-modal-back-button
`
`bash
pnpm add react-modal-back-button
`
The Problem
When a modal is open and users press the back button (especially on mobile), the browser navigates to the previous page instead of closing the modal. This breaks the expected user experience and can cause data loss.
The Solution
This hook intercepts back button presses and closes your modal instead, creating an intuitive mobile-native experience that users expect.
Usage
$3
`jsx
import { useModalBackButton } from 'react-modal-back-button';
function MyComponent() {
const { isOpen, open, close } = useModalBackButton();
return (
{isOpen && (
My Modal
)}
);
}
`
$3
#### React Modal
`jsx
import Modal from 'react-modal';
import { useModalBackButton } from 'react-modal-back-button';
function MyComponent() {
const { isOpen, open, close } = useModalBackButton();
return (
<>
Hello Modal
>
);
}
`
#### Material-UI (MUI)
`jsx
import { Dialog, DialogTitle, DialogContent, Button } from '@mui/material';
import { useModalBackButton } from 'react-modal-back-button';
function MyComponent() {
const { isOpen, open, close } = useModalBackButton();
return (
<>
>
);
}
`
#### Headless UI
`jsx
import { Dialog } from '@headlessui/react';
import { useModalBackButton } from 'react-modal-back-button';
function MyComponent() {
const { isOpen, open, close } = useModalBackButton();
return (
<>
>
);
}
`
Options
`typescript
const { isOpen, open, close, toggle } = useModalBackButton({
key: 'my-modal',
enabled: true,
pushStateOnOpen: true,
cleanupOnClose: true
});
`
$3
- key: A unique identifier for the modal. Useful when you have multiple modals. Auto-generated if not provided.
- enabled: Set to false to temporarily disable the hook without unmounting.
- pushStateOnOpen: When true (default), adds a history entry when the modal opens. Set to false if you manage history yourself.
- cleanupOnClose: When true (default), removes the history entry when you close the modal programmatically (e.g., clicking a close button). Set to false to keep the history entry.
How It Works
The hook manages browser history to create seamless back button support:
1. Modal Opens: Pushes a new history entry to the browser stack
2. Back Button Pressed: Intercepts the popstate event and closes the modal
3. Modal Closed Programmatically: Automatically removes the history entry to prevent navigation issues
4. Smart Detection: Distinguishes between back button closes and programmatic closes to handle cleanup correctly
This ensures the back button works exactly as users expect, without breaking browser navigation.
API Reference
$3
#### Parameters
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| options | UseModalBackButtonOptions | No | Configuration options |
#### Returns
| Property | Type | Description |
|----------|------|-------------|
| isOpen | boolean | Current state of the modal |
| open | () => void | Function to open the modal |
| close | () => void | Function to close the modal |
| toggle | () => void | Function to toggle modal state |
#### Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| key | string | auto-generated | Unique identifier for the modal. Useful when managing multiple modals |
| enabled | boolean | true | Enable or disable the hook without unmounting |
| pushStateOnOpen | boolean | true | Whether to push a history entry when modal opens |
| cleanupOnClose | boolean | true | Whether to remove history entry when modal closes programmatically |
TypeScript
Full TypeScript support is included with complete type definitions.
`typescript
import {
useModalBackButton,
UseModalBackButtonOptions,
UseModalBackButtonReturn
} from 'react-modal-back-button';
const options: UseModalBackButtonOptions = {
key: 'my-modal',
enabled: true,
pushStateOnOpen: true,
cleanupOnClose: true
};
const { isOpen, open, close, toggle }: UseModalBackButtonReturn = useModalBackButton(options);
`
Advanced Usage
$3
When working with multiple modals, provide unique keys to avoid conflicts:
`jsx
function App() {
const settings = useModalBackButton({ key: 'settings-modal' });
const profile = useModalBackButton({ key: 'profile-modal' });
return (
<>
{settings.isOpen && }
{profile.isOpen && }
>
);
}
`
$3
Use the built-in toggle function for convenience:
`jsx
function App() {
const { isOpen, toggle } = useModalBackButton();
return (
<>
{isOpen && }
>
);
}
`
$3
Disable the hook based on conditions without unmounting:
`jsx
const isMobile = useMediaQuery('(max-width: 768px)');
const { isOpen, open, close } = useModalBackButton({
enabled: isMobile
});
`
$3
If you manage history yourself, disable automatic pushing:
`jsx
const { isOpen, open, close } = useModalBackButton({
pushStateOnOpen: false
});
`
Browser Support
Works in all modern browsers that support the History API:
- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- iOS Safari (latest)
- Chrome Android (latest)
FAQ
Q: Does this work with Next.js?
A: Yes! The hook is SSR-safe and works perfectly with Next.js and other SSR frameworks.
Q: Can I use this with multiple modals?
A: Yes, provide a unique key` option for each modal instance.