πΌ React hook for Modals
Simple, lightweight hook for Modals/Dialogs.
This hook is also isomorphic, meaning it works with SSR (server side rendering).
- SSR (server side rendering) support
- TypeScript support
- 2 dependencies (use-ssr, react-useportal)
- Built in state
yarn add use-react-modal or npm i -S use-react-modal
import useModal from 'use-react-modal'
const App = () => {
const { isOpen, openModal, closeModal, Modal } = useModal()
return (
<>
<button onClick={openModal}>Open Me!</button>
{isOpen && (
<Modal>
<button onClick={closeModal}>close</button>
Whatever you put here will be centered to the middle of the screen.
</Modal>
)
</>
)
}
import useModal, { Provider } from 'use-react-modal'
const MyComponent = () => {
const { isOpen, openModal, Modal } = useModal()
return (
<>
<button onClick={openModal}>Open Me!</button>
{isOpen && (
<Modal>
Now, whatever you put here will be centered AND have a backdrop
with the color specified in the Provider
</Modal>
)
</>
)
}
const App = () => (
<Provider background='rgba(0, 0, 0, 0.5)'>
<MyComponent />
</Provider>
)
Make sure you are passing the html synthetic event to the openModal
and toggleModal
. i.e. onClick={e => openModal(e)}
If for some reason, you don't want to pass around the event
to openModal
or toggleModal
, you can use a targetRef
like this.
import useModal from 'use-react-modal'
const App = () => {
const { targetRef, openModal, closeModal, isOpen, Modal } = useModal()
return (
<>
{/* see below how I don't have to pass the event if I use the ref */}
<button ref={targetRef} onClick={() => openModal()}>
Open Modal
</button>
{isOpen && (
<Modal>
<p>
<button onClick={closeModal}>Close me!</button>, hit ESC or
Cool Modal π
</p>
</Modal>
)}
</>
)
}
Option | Description |
---|---|
background |
sets the color of the backdrop, if nothing is set, there will be no backdrop |
closeOnOutsideClick |
This will close the modal when not clicking within the modal. Default is true |
closeOnEsc |
This will allow you to hit ESC and it will close the modal. Default is true |
bindTo |
This is the DOM node you want to attach the modal to. By default it attaches to document.body |
isOpen |
This will be the default for the modal being open or closed. Default is false |
onOpen |
This is used to call something when the modal is opened |
onClose |
This is used to call something when the modal is closed |
html event handlers (i.e. onClick ) |
These can be used instead of onOpen . |
const {
openModal,
closeModal,
toggleModal,
isOpen,
Modal,
// if you don't pass an event to openModal, closeModal, or toggleModal, you will need to
// put this on the element you want to interact with/click to open the modal
targetRef,
// this allows you to interact directly with the backdrop/overlay
backdropRef,
// this allows you to interact directly with the modal
modalRef,
} = useModal({
// sets the color of the backdrop, if nothing is set, the backdrop will be transparent unless it's set in the Provider
// setting to `null` removes any background set in the `Provider`
background: 'rgba(0, 0, 0, 0.5)',
closeOnOutsideClick: true,
closeOnEsc: true,
bindTo, // attach the portal to this node in the DOM
isOpen: false,
// `event` has all the fields that a normal `event` would have such as `event.target.value`, etc.
// with the additional `portal` and `targetEl` added to it as seen in the examples below
onOpen: (event) => {
// can access: event.portal, event.targetEl, event.event, event.target, etc.
},
// `onClose` will not have an `event` unless you pass an `event` to `closePortal`
onClose({ targetEl, event, portal }) {},
// `targetEl` is the element that you either are attaching a `ref` to
// or that you are putting `openPortal` or `togglePortal` or `closePortal` on
// in addition, any event handler such as onClick, onMouseOver, etc will be handled the same
onClick({ targetEl, event, portal }) {}
})
Can also do array destructuring
const [openModal, closeModal, isOpen, Modal, toggleModal, targetRef, portalRef, modalRef] = useModal()
- animations π
- React Native support. 1 2 3 4 5 Probably going to have to add a
Provider
... - add correct return types
- tests (priority)
- potential syntax ideas
// then you can change the order of the array destructuring syntax <Provider order={['Modal', 'openModal']} /> // CustomModal, CustomCloseButton <Provider Modal={CustomModal} CloseButton={CustomClostButton} /> const { Modal, CloseButton } = useProvider() // customize the modal animations const { Modal } = useModal({ onOpen({ modal }) { modal.current.style.cssText = ` /* do some animation in */ ` }, onClose({ modal }) { modal.current.style.cssText = ` /* do some animation out */ ` } }) // customize the modal animations idea 2 const { Modal } = useModal({ animateIn: ` /* css for animating in */ `, animateOut: ` /* css for animating out */ `, }) // customize the modal animations idea 3 // maybe have some predefined options? const { Modal } = useModal({ animate: 'fade-in-out', // 'slide-in-top', etc... }) // check out http://reactcommunity.org/react-modal/styles/transitions.html