Skip to content

Instantly share code, notes, and snippets.

@Fausto95
Last active December 14, 2023 18:52
Show Gist options
  • Select an option

  • Save Fausto95/2634f545e7be6dc8ab3caa55b9ffaa00 to your computer and use it in GitHub Desktop.

Select an option

Save Fausto95/2634f545e7be6dc8ab3caa55b9ffaa00 to your computer and use it in GitHub Desktop.
React Native Modal Queue
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,
},
});
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,
},
});
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}
/>
);
};
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}
/>
);
};
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"
/>
);
};
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