mui-modal-provider is a lightweight utility built on top of React Context API and Hooks to simplify managing Material-UI modals (dialogs). It allows you to trigger modals imperatively from anywhere in your component tree without managing local open states.
npm install mui-modal-provider # or yarn add mui-modal-provider- Wrap your app with
ModalProvider:
import React from 'react';
import { createRoot } from 'react-dom/client';
import ModalProvider from 'mui-modal-provider';
import App from './App';
const root = createRoot(document.getElementById('root'));
root.render(
<ModalProvider>
<App />
</ModalProvider>
);- Trigger modals using
useModal:
import React from 'react';
import { useModal } from 'mui-modal-provider';
import Dialog from '@mui/material/Dialog';
import DialogTitle from '@mui/material/DialogTitle';
import Button from '@mui/material/Button';
const SimpleDialog = ({ title, ...props }) => (
<Dialog {...props}>
<DialogTitle>{title}</DialogTitle>
</Dialog>
);
const App = () => {
const { showModal } = useModal();
return (
<Button
variant="contained"
onClick={() => showModal(SimpleDialog, { title: 'Hello World' })}
>
Open Dialog
</Button>
);
};| Property | Type | Default | Description |
|---|---|---|---|
legacy |
boolean |
false |
Set to true if you are using MUI v4 or below. |
suspense |
boolean |
true |
Wraps modals in Suspense for lazy loading support. |
fallback |
ReactNode |
null |
Loading fallback for Suspense. |
The useModal hook returns an object with the following methods:
showModal(Component, props, options): Displays a modal.hideModal(id): Hides a specific modal by ID.destroyModal(id): Removes a specific modal from the DOM immediately.updateModal(id, props): Updates the props of an active modal.destroyModalsByRootId(rootId): Destroys all modals associated with a specific root ID.
The third argument of showModal accepts an options object:
| Property | Type | Default | Description |
|---|---|---|---|
hideOnClose |
boolean |
true |
Automatically calls hideModal when onClose is triggered. |
destroyOnClose |
boolean |
false |
Automatically calls destroyModal after the closing transition. |
rootId |
string |
uid |
A custom ID used for group destruction. |
showModal returns a modal instance object:
id: The unique ID of the modal.hide(): Hides the modal.destroy(): Destroys the modal.update(newProps): Updates the modal's props.
You can update an existing modal's props without closing and re-opening it:
const modal = showModal(SimpleDialog, { title: 'Loading...' });
// Later...
modal.update({ title: 'Success!' });Since ModalProvider supports Suspense, you can easily use React.lazy for your modals:
const LazyDialog = React.lazy(() => import('./LazyDialog'));
// ...
showModal(LazyDialog, { someProp: 'value' });By default, useModal automatically destroys any modals it created when the component using the hook unmounts. This prevents memory leaks and stale modals.
You can disable this behavior if needed:
const { showModal } = useModal({ disableAutoDestroy: true });You can globally configure the library behavior:
import { setModalConfig } from 'mui-modal-provider';
setModalConfig({
enforceProvider: true, // Throws an error if useModal is used outside ModalProvider
});For Material-UI v4, set the legacy prop on ModalProvider:
<ModalProvider legacy>
<App />
</ModalProvider>Because this module utilizes react hooks, it must be linked in a special way that is described here in this react github issue comment
- Update the react and react-dom versions in this module’s package.json devDependencies match the versions in whatever project you’re linking them in.
yarn installin this module’s root directory- Because this module uses hooks, we need to link the module’s react dependency into the project we will be using to test the linked module
cd node_modules/reactthenyarn linkthen inside your linked project runyarn link react- In the linked project’s root directory run
yarn install mui-modal-provider - Then in the module’s root directory run
yarn link - In the linked project’s root directory run
yarn link mui-modal-provider