The goal is to be as close to this as possible
Last active
December 14, 2023 18:52
-
-
Save Fausto95/2634f545e7be6dc8ab3caa55b9ffaa00 to your computer and use it in GitHub Desktop.
React Native Modal Queue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useModals, ModalsIndexContextProvider } from './useModals'; | |
| import { SafeAreaView, StyleSheet, Text } from 'react-native'; | |
| function App_() { | |
| const Modal = useModals(); | |
| return ( | |
| <SafeAreaView style={styles.container}> | |
| <Text>Hello</Text> | |
| {Modal} | |
| </SafeAreaView> | |
| ); | |
| } | |
| export default function App() { | |
| return ( | |
| <ModalsIndexContextProvider> | |
| <App_ /> | |
| </ModalsIndexContextProvider> | |
| ); | |
| } | |
| const styles = StyleSheet.create({ | |
| container: { | |
| flex: 1, | |
| backgroundColor: '#ecf0f1', | |
| justifyContent: 'center', | |
| padding: 8, | |
| }, | |
| }); | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import RNModal from 'react-native-modal'; | |
| import { Text, StyleSheet, View, Pressable } from 'react-native'; | |
| export const Modal = ({ title, isVisible, jumpToNextModal }) => { | |
| return ( | |
| <RNModal | |
| isVisible={isVisible} | |
| hideModalContentWhileAnimating | |
| hasBackdrop | |
| backdropOpacity={0.75} | |
| backdropColor={'grey'} | |
| testID="modal3" | |
| animationOut="fadeOut" | |
| style={styles.modal} | |
| onModalHide={jumpToNextModal} | |
| useNativeDriver> | |
| <View style={styles.container}> | |
| <Text>{title}</Text> | |
| <Pressable style={styles.button} onPress={jumpToNextModal}> | |
| <Text>Hide {title}</Text> | |
| </Pressable> | |
| </View> | |
| </RNModal> | |
| ); | |
| }; | |
| const styles = StyleSheet.create({ | |
| modal: { | |
| padding: 0, | |
| margin: 0, | |
| flex: 1, | |
| backgroundColor: 'white', | |
| position: 'absolute', | |
| borderTopLeftRadius: 10, | |
| borderTopRightRadius: 10, | |
| width: '100%', | |
| bottom: 0, | |
| }, | |
| button: { | |
| borderWidth: 2, | |
| margin: 2, | |
| padding: 5, | |
| backgroundColor: 'green', | |
| }, | |
| container: { | |
| height: 400, | |
| }, | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState, useEffect } from 'react'; | |
| import { Modal } from './Modal'; | |
| const someHeavyCalculation = () => { | |
| const random = Math.floor(Math.random() * 3); | |
| if (random === 1) return Promise.resolve(true); | |
| return Promise.resolve(false); | |
| }; | |
| export const Modal1 = ({ jumpToNextModal }) => { | |
| const [isVisible, setIsVisible] = useState(true); | |
| useEffect(() => { | |
| someHeavyCalculation().then((result) => { | |
| if (result) { | |
| setIsVisible(result); | |
| } else { | |
| jumpToNextModal(); | |
| } | |
| }); | |
| }, [jumpToNextModal]); | |
| return ( | |
| <Modal | |
| title="Modal 1" | |
| jumpToNextModal={jumpToNextModal} | |
| isVisible={isVisible} | |
| /> | |
| ); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState, useEffect } from 'react'; | |
| import { Modal } from './Modal'; | |
| const someHeavyCalculation = () => { | |
| const random = Math.floor(Math.random() * 3); | |
| if (random === 2) return Promise.resolve(true); | |
| return Promise.resolve(false); | |
| }; | |
| export const Modal2 = ({ jumpToNextModal }) => { | |
| const [isVisible, setIsVisible] = useState(true); | |
| useEffect(() => { | |
| someHeavyCalculation().then((result) => { | |
| if (result) { | |
| setIsVisible(result); | |
| } else { | |
| jumpToNextModal(); | |
| } | |
| }); | |
| }, [jumpToNextModal]); | |
| return ( | |
| <Modal | |
| title="Modal 2" | |
| jumpToNextModal={jumpToNextModal} | |
| isVisible={isVisible} | |
| /> | |
| ); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState, useEffect } from 'react'; | |
| import { Modal } from './Modal'; | |
| const someHeavyCalculation = () => { | |
| const random = Math.floor(Math.random() * 3); | |
| if (random === 3) return Promise.resolve(true); | |
| return Promise.resolve(false); | |
| }; | |
| export const Modal3 = ({ jumpToNextModal }) => { | |
| const [isVisible, setIsVisible] = useState(true); | |
| useEffect(() => { | |
| someHeavyCalculation().then((result) => { | |
| if (result) { | |
| setIsVisible(result); | |
| } else { | |
| jumpToNextModal(); | |
| } | |
| }); | |
| }, [jumpToNextModal]); | |
| return ( | |
| <Modal | |
| jumpToNextModal={jumpToNextModal} | |
| isVisible={isVisible} | |
| title="Modal 3" | |
| /> | |
| ); | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Modal1 } from './Modal1'; | |
| import { Modal2 } from './Modal2'; | |
| import { Modal3 } from './Modal3'; | |
| import { | |
| useState, | |
| createContext, | |
| useCallback, | |
| useContext, | |
| useMemo, | |
| } from 'react'; | |
| export const ModalsIndexContext = createContext({ | |
| index: 0, | |
| setIndex: () => undefined, | |
| }); | |
| export const ModalsIndexContextProvider = ({ children }) => { | |
| const [index, setIndex] = useState(0); | |
| return ( | |
| <ModalsIndexContext.Provider value={{ index, setIndex }}> | |
| {children} | |
| </ModalsIndexContext.Provider> | |
| ); | |
| }; | |
| export const useModals = () => { | |
| const { index, setIndex } = useContext(ModalsIndexContext); | |
| const queue = useMemo(() => [Modal1, Modal2, Modal3], []); | |
| const jumpToNextModal = useCallback(() => { | |
| setIndex((prev) => { | |
| const nextIndex = prev + 1; | |
| return nextIndex; | |
| }); | |
| }, [setIndex]); | |
| const CurrentModal = useMemo(() => { | |
| const queueLength = queue.length - 1; | |
| if (index > queueLength) return null; | |
| const Component = queue[index]; | |
| return Component; | |
| }, [queue, index]); | |
| if (CurrentModal === null) return null; | |
| return <CurrentModal jumpToNextModal={jumpToNextModal} />; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
