- Uses pure JS
- Does not use the additional native layer used by react-native's implementation
- Fixes Android bugs associated with touch events
- Uses hooks, rather than adding things to a component's render that aren't displayed
- Has four animation types
- No additional dependencies
yarn:
$ yarn add @idiosync/react-native-modal
npm:
$ npm i @idiosync/react-native-modal
First, to use this library, you must wrap your entire app in with <ModalContextLayer>
const App = () => {
return (
// NOTE: if you need to access any context from inside your modal, such as redux
// you need to place the ModalContextLayer inside the provider for that context
<ModalContextLayer>
{...App goes here...}
</ModalContextLayer>
)
}
The simplest implementation uses the useModal hook and controls viability at the component where the hook is being used
import { useModal } from "@idiosync/react-native-modal"
const SomeComponent = () => {
const [modalIsVisible, setModalIsVisible] = useState(false)
useModal(
{
// all config params are optional apart from renderModal
renderModal: () => <MyModal onClose={() => setModalIsVisible(false)} someProp={someProp} />,
onBackgroundPress: () => setModalIsVisible(false),
animationTypeIn: AnimationType.SLIDE_TOP,
contentContainerStyle: { width: '100%' }
},
modalIsVisible,
[someProp] // dependencies array to trigger rerenders. Empty array is passed by default
)
return (
<OpenButton onPress={() => setModalIsVisible(true) />
)
}
When using the useModalTrigger hook, the viability is handled automatically and functions are returned to open and close the modal
const SomeComponent = () => {
// the onClose function is received via the render function
// and passed into the modal component
const { openModal, closeModal } = useModalTrigger({
renderModal: ({ onClose }) => <MyModal onClose={onClose} />,
})
return (
<>
<OpenButton onPress={openModal} />
<CloseButton onPress={closeModal} />
</>
)
Finally - a situation often arises in which a component has a series of modals, all of which open based on a state, or a set of variables. This can be streamlined with useModalSwitch
const SomeComponent = () => {
const [currentModal, setCurrentModal] = useState(MODAL_1)
// The hook accepts an array or arrays. The nested arrays
// contain the render function, the condition that specifies isVisible
// and the modal options
useModalSwitch([
[
{ renderModal: () => <Modal1 onClose={() => setCurrentModal(MODAL_2)} /> },
currentModal === MODAL_1,
],
[
{
renderModal: () => <Modal2 onClose={() => setCurrentModal(MODAL_3)} someParam={someParam} />,
...options,
},
currentModal === MODAL_2,
[someParam] // depencencies added per modal
],
[
{ renderModal: () => <Modal3 onClose={() => setCurrentModal(NONE)} /> },
currentModal === MODAL_3,
]
])
return (
<SomeOtherComponent onShowModal={() => setModalIsVisible(true) />
)
}
Arguments:
- config - config object for you modal - must include your renderModal function
- isVisible - boolean that specifies whether the modal should be rendered
- dependencies - An array of dependecied for shallow checking. When these change, the modal rerenders. They will often be the same as your modals properties
Returned interface:
- removeModal - Instantly removes modal with no out animation
Arguments:
- config - config object for you modal - must include your renderModal function
- dependencies - An array of dependecied for shallow checking. When these change, the modal rerenders.
Returned interface:
- openModal - Triggers modal to start animating in
- closeModal - Triggers modal to start animating out
- removeModal - Instantly removes modal with no out animation
Arguments:
- modalConfigArray - An array of arrays, each with 2 / 3 elements
- [0] - config - config object for you modal - must include your renderModal function
- [1] - isVisible - boolean that specifies whether the modal should be rendered
- [2] - dependencies - An array of dependecied for shallow checking. When these change, the modal rerenders.
- renderModal- Render function which is passed an interface, and returns your bespoke modal component
- onBackgroundPress(optional) - Callback triggered by the background being pressed
- animationTypeIn(optional) - Animation type used when modal appears
- animationTypeOut(optional) - Animation type used when modal disappears
- backgroundFadeDuration(optional) - The time taken for the background to animate
- backgroundFadeOutDelay(optional) - Time after which the background animates out once modal is closed
- animationTimeIn(optional) - Time taken to animate in
- animationTimeOut(optional) - Time taken to animate out
- onModalClosed(optional) - Called when modal start to animate out
- onModalRemoved(optional) - Called when animation out is completed, and modal is removed
- contentContainerStyle - Pass a style in to effect the container, for example to make it fill the screen. Be aware that filling the screen will stop you being able to click the background.
- alignModal - horiontally align the modal within its parent container using the enum ModalAlign (START|END|CENTER).
- justifyModal - vertically align the modal within its parent container using the enum ModalAlign (START|END|CENTER).
Animations types found on the AnimationType enum
- FADE - Fade in or out
- SLIDE_TOP - Slide in from, or out to the top of the screen
- SLIDE_BOTTOM - Slide in from, or out to the bottom of the screen
- SLIDE_LEFT - Slide in from, or out to the left of the screen
- SLIDE_RIGHT - Slide in from, or out to the right of the screen