visit
A guide on how to master React Native modal complex flows.
Do you find using modals in React Native to be a bit of a pain? You’re not alone! Trying to keep control of its open state and repeating the code everywhere you want to use it can be pretty tedious.
And the problem only gets worse when you try to create complex flows. Once you get past two modals, your main component is a mess, and the state is all over the place. I’ve experienced this first-hand in many big companies, like Zé Delivery (by AB-InBev), Alfred Delivery, and now at X-Team.
This article's teachings have been encapsulated in this library: .
a. If the user rates it with less than four stars, show another modal asking for feedback on how to improve.
b. Otherwise, show a happy modal asking the user to rate us on the app store.
Finally, show a ‘thanks’ modal, thanking the user for their support.
import React, { useState, useImperativeHandle } from 'react';
import { Text } from 'react-native';
import ModalContainer from 'react-native-modal';
export const ExampleModal = React.forwardRef((ref) => {
const [isVisible, setIsVisible] = useState(false);
const show = () => setIsVisible(true);
const hide = () => setIsVisible(false);
useImperativeHandle(ref, () => ({ hide, show }));
return (
<ModalContainer onBackdropPress={hide} isVisible={isVisible}>
<Text>My awesome modal!</Text>
</ModalContainer>
);
});
That's the transition to a better place.
ref
prop from a useRef
hook, which means we can't call show
outside React components.ExampleModal
repeated.
import React, { useState, useImperativeHandle } from 'react';
import { Text } from 'react-native';
import ModalContainer from 'react-native-modal';
export const imperativeModalRef = React.createRef();
export const SmartExample = () => {
const [isVisible, setIsVisible] = useState(false);
const show = () => setIsVisible(true);
const hide = () => setIsVisible(false);
useImperativeHandle(imperativeModalRef, () => ({ hide, show }));
return (
<ModalContainer onBackdropPress={hide} isVisible={isVisible}>
<Text>My awesome modal!</Text>
</ModalContainer>
);
};
Now imperativeModalRef
can be imported and used anywhere, as long as SmartExample
is on the root. We can use show and hide from every component, function, or
That's where you can get creative with abstractions to make the SmartExample
render any modal you want! One way to do this is to make the show
function receive a component and render it.
Instead of making you guys reinvent the wheel, I've created an open-source library that encapsulates all these concepts and more, with full TypeScript support based on
"Talk is cheap. Show me the code." ― Linus Torvalds.
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { MagicModalPortal, magicModal } from 'react-native-magic-modal';
const ConfirmationModal = () => (
<View>
<TouchableOpacity onPress={() => magicModal.hide({ success: true })}>
<Text>Click here to confirm</Text>
</TouchableOpacity>
</View>
);
const ResponseModal = ({ text }) => (
<View>
<Text>{text}</Text>
<TouchableOpacity onPress={() => magicModal.hide()}>
<Text>Close</Text>
</TouchableOpacity>
</View>
);
const handleConfirmationFlow = async () => {
// We call it with or without props, depending on the requirements of the modal.
const result = await magicModal.show(ConfirmationModal);
if (result.success) {
return magicModal.show(() => <ResponseModal text="Success!" />);
}
return magicModal.show(() => <ResponseModal text="Failure :(" />);
};
export const MainScreen = () => {
return (
<View>
<TouchableOpacity onPress={handleConfirmationFlow}>
<Text>Start the modal flow!</Text>
</TouchableOpacity>
<MagicModalPortal />
</View>
);
};
Example using react-native-magic-modal
Did you know that, in React Native, you can’t show two modals simultaneously?
Even if you try to show a modal right after another, it would probably fail as the last modal is still animating its ‘close’ state. Fortunately, the issue is already dealt with on our side.
This same logic has already been battle-tested on big companies I’ve worked on, like Zé Delivery (by AB-InBev), Alfred Delivery, and X-Team.
The
Thanks for the read. If you liked the article, follow me on and .
Also Published