A React modal that can be used with Promise.
npm install async-modal-reactModalProvider and use useModal hook.
bash
npm install async-modal-react@3 # react <=18
npm install async-modal-react@latest # react >=19
`
Usage
$3
- closeOnOutsideClick props is for close modal when click outside of modal(default: true).
- disableBodyScrollWhenOpen props is for disable body scroll when modal is opened(default: true).
- closeOnRouteChange props is for close all modals when route is changed(default: true).
- errorOnClose props is for throw error when modal is closed by clicking outside of modal or route change(default: false).
`jsx
import { ModalProvider } from "async-modal-react";
ReactDOM.createRoot(document.getElementById("root")).render(
closeOnOutsideClick={true}
disableBodyScrollWhenOpen={true}
closeOnRouteChange={true}
>
,
);
`
$3
- Component that used for modal receive 3 props: close, resolve, reject.
- resolve function will return value when using open function.
- close and reject function will reject when using open function.
- reject reason and resolve value can customize by yourself.
> ❗close estimated as reject
`jsx
const ExampleModal = ({ close, resolve, reject }) => {
return (
ExampleModal
);
};
export default ExampleModal;
`
$3
- useModal hook return open and closeAll function.
`jsx
import ExampleModal from "./components/ExampleModal";
import { useModal } from "async-modal-react";
function App() {
const { open, closeAll } = useModal();
const openModal = async () => {
try {
// resolve
const result = await open(ExampleModal);
console.log(result);
} catch (e) {
// reject, close
console.log(e);
}
};
return (
);
}
export default App;
`
Typescript Support
$3
- import ModalProps from async-modal-react and extend your props interface.
`ts
export interface ModalProps {
close: () => void;
resolve: (v: Result) => void;
reject: (reason: Reason) => void;
}
`
`tsx
import { ModalProps } from "async-modal-react";
export interface ExampleProps extends ModalProps {
name: string;
}
const ExampleModal = ({ close, resolve, reject, name }: ExampleProps) => {
return (
ExampleModal
);
};
export default ExampleModal;
`
$3
- resolve type can be set by generic type.
- second generic type is for modal props. (most case is not necessary)
- open function return Promise.
- options are higher priority than ModalProvider props. You can set individually.
`tsx
const result = await open(
ExampleModal, // Modal Component
{}, // ExampleModal props
{ // Individual options
onClickOutsideClose: true,
disableScroll: true,
enableInsideScroll: true, // use this when global disableScroll is true but you want to enable scroll in this modal.
errorOnClose: true,
},
);
`
Customizing
$3
`jsx
id="modal-root"
style={{
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
background: "rgba(0, 0, 0, 0.5)",
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
{children}
customize #modal-root element with global css.
`css
#modal-root {
background: blue !important;
}
`
$3
By Default modal root element display children with flex and justifyContent: center, alignItems: center. So if there are more than two modal is opened, they will be displayed in just like a flex.
if you want to stack layout, your modal component should have position: absolute style.
`jsx
// ...
return (
style={{
background: "white",
position: "absolute",
}}
>
ExampleModal
resolve! ${name})}>RESOLVE
#### If Modal Component not have position: absolute look like.
!multi-modal-flex.png
#### If Modal Component have position: absolute` look like.