use-modal-react v1.0.0
React Use Modal
react-use-modal
is a hook meant to take care of state management for modals, instead of requiring you to do so. This library does not provide a component for rendering modals, but it allows you to choose what components to use.
Table of Content
Context - Without react-use-modal
Consider the following example:
function MyModalComponent(props) {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button onClick={() => setIsOpen(true)}>
Open Modal
</Button>
<Modal isOpen={isOpen} onHide={() => setIsOpen(false)}>
<ModalContents/>
</Modal>
</>
);
}
What's bad about this is that in every component we need a modal, we will have to: 1. create a state for the modal opening 2. render the actual modal content alongside the rest of the components tree
Basic Usage - With react-use-modal
First things first, we want to make sure the modal context is available, so add the ModalProvider
somewhere up the tree (like your main.js
):
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<ModalProvider variants={Modal}>
<App/>
</ModalProvider>
</React.StrictMode>
);
The
variants
prop is the component used to actually render the Modal. Read the API description.
The example above could be written as:
function MyModalComponent(props) {
const openModal = useModal(ModalContents);
return (
<Button onClick={openModal}>
Open Modal
</Button>
);
}
The
useModal
hook is fairly customizable. Read the API description.
API
1. ModalProvider
component
The provider of the Modal Context. This library cannot be used without this.
Property Name | Accepted Types | Description |
---|---|---|
variants | Component \| Object | All possible variants of modals. |
2. useModal(useComponent: Component, options?: HookProps, deps = []): OpenModalFn
The actual hook responsible with the magic. It accepts 3 parameters.
Parameter Name | Accepted Types | Description |
---|---|---|
useComponent | Component | The component rendered as modal content. |
options (optional) | HookProps | Additional options for modal customization (check table below). |
deps (optional) | Array | React dependency array. There aren't really many usecases for using this.Default value: [] |
3. Additional options accepted by the useModal
hook:
Property Name | Accepted Types | Description |
---|---|---|
variant (optional) | string | The modal variant to be used. Must be one of the specified variants.Default value: default |
isDefaultOpen (optional) | boolean | Controls whether the modal should be opened by default or not.Default value: false |
onHide (optional) | (params: any) => any | Function called when the modal is closed. Accepts one parameter. |
props (optional) | Object | Properties passed to the Modal variant rendered. |
componentProps (optional) | Object | Properties passed to the component rendered inside the modal. |
4. Return: OpenModalFn: (params: IDynamicParams) => any
A function that opens the modal when called. It accepts one parameter of type
Object
that will be used as theparams
prop of the modal content component.
Example Usages
1. Custom Modal Variant & Props
import Modal from '/my-components/modals/Modal';
import RedModalVariant from '/my-components/modals/RedModalVariant';
// variants used in ModalProvider
const variants = {
default: Modal,
'red-modal': RedModalVariant,
};
// MyComponent.js
function MyComponent() {
const openModal = useModal(ModalContentComponent, {
variant: 'red-modal',
props: { // will be passed to the RedModalVariant component
size: 'lg',
},
componentProps: { // will be passed to the ModalContentComponent
content: 'hello world',
},
});
return (
<button onClick={openModal}>
Open Modal
</button>
);
}
2. Dynamic Content
When you have a list of items, instead of rendering a modal for all of the items (hence, managing multiple component states), you can do something like this:
// MyComponent.js
function MyComponent() {
const [list, setList] = useState([]);
useEffect(fetchMyList, []);
const openModal = useModal(EditListItemModal, {
componentProps: {
title: 'Edit Item',
},
});
return (
<ul>
{list.map(item => (
<li key={item.id} onClick={() => openModal(item)} />
))}
</ul>
);
}
// EditListItemModal.js
function EditListItemModal({ title, params: item }) {
// the dynamic params prop will be the item passed when openModal got called
// title, however, is a static prop passed when the modal is initialized
}
This way, you can use the same modal instance, while only changing the data used to render the content.
2 years ago