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.

Revisions

  1. Fausto95 revised this gist Dec 14, 2023. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -3,4 +3,6 @@
    The goal is to be as close to this as possible


    [Expo Snack Demo](https://snack.expo.dev/@fausto95/react-native-modal-queue)
    [Expo Snack Demo 1](https://snack.expo.dev/@fausto95/react-native-modal-queue) by [Fausto95](https://github.com/Fausto95)

    [Expo Snack Demo 2](https://snack.expo.dev/@brunokiafuka/modalwrapper) by [Bruno](https://github.com/BrunoKiafuka)
  2. Fausto95 revised this gist Dec 14, 2023. 4 changed files with 19 additions and 13 deletions.
    11 changes: 8 additions & 3 deletions App.js
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,16 @@
    import { useModals, ModalsIndexContextProvider } from './useModals';

    import { SafeAreaView, StyleSheet } from 'react-native';
    import { SafeAreaView, StyleSheet, Text } from 'react-native';

    function App_() {
    const Modal = useModals();

    return <SafeAreaView style={styles.container}>{Modal}</SafeAreaView>;
    return (
    <SafeAreaView style={styles.container}>
    <Text>Hello</Text>
    {Modal}
    </SafeAreaView>
    );
    }

    export default function App() {
    @@ -19,8 +24,8 @@ export default function App() {
    const styles = StyleSheet.create({
    container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    justifyContent: 'center',
    padding: 8,
    },
    });
    6 changes: 3 additions & 3 deletions Modal.js
    Original file line number Diff line number Diff line change
    @@ -7,11 +7,11 @@ export const Modal = ({ title, isVisible, jumpToNextModal }) => {
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    backdropColor={'grey'}
    testID="modal3"
    style={styles.modal}
    animationOut="fadeOut"
    style={styles.modal}
    onModalHide={jumpToNextModal}
    useNativeDriver>
    <View style={styles.container}>
    @@ -28,8 +28,8 @@ const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    backgroundColor: 'white',
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    3 changes: 1 addition & 2 deletions Modal3.js
    Original file line number Diff line number Diff line change
    @@ -22,10 +22,9 @@ export const Modal3 = ({ jumpToNextModal }) => {

    return (
    <Modal
    title="Modal 3"
    jumpToNextModal={jumpToNextModal}
    isVisible={isVisible}
    title="Modal 3"
    />
    );
    };

    12 changes: 7 additions & 5 deletions useModals.js
    Original file line number Diff line number Diff line change
    @@ -3,10 +3,10 @@ import { Modal2 } from './Modal2';
    import { Modal3 } from './Modal3';
    import {
    useState,
    createContext,
    useCallback,
    useMemo,
    useContext,
    createContext,
    useMemo,
    } from 'react';

    export const ModalsIndexContext = createContext({
    @@ -27,7 +27,7 @@ export const ModalsIndexContextProvider = ({ children }) => {
    export const useModals = () => {
    const { index, setIndex } = useContext(ModalsIndexContext);

    const queue = useMemo(() => [() => Modal1, () => Modal2, () => Modal3], []);
    const queue = useMemo(() => [Modal1, Modal2, Modal3], []);

    const jumpToNextModal = useCallback(() => {
    setIndex((prev) => {
    @@ -39,11 +39,13 @@ export const useModals = () => {
    const CurrentModal = useMemo(() => {
    const queueLength = queue.length - 1;

    if (index > queueLength) return () => null;
    if (index > queueLength) return null;

    const Component = queue[index]();
    const Component = queue[index];
    return Component;
    }, [queue, index]);

    if (CurrentModal === null) return null;

    return <CurrentModal jumpToNextModal={jumpToNextModal} />;
    };
  3. Fausto95 revised this gist Dec 14, 2023. 1 changed file with 0 additions and 10 deletions.
    10 changes: 0 additions & 10 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +0,0 @@
    import { ModalsIndexContextProvider } from './useModals';
    import App_ from './App.js';

    export default function App() {
    return (
    <ModalsIndexContextProvider>
    <App_ />
    </ModalsIndexContextProvider>
    );
    }
  4. Fausto95 revised this gist Dec 14, 2023. 1 changed file with 48 additions and 0 deletions.
    48 changes: 48 additions & 0 deletions Modal.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,48 @@
    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
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal3"
    style={styles.modal}
    animationOut="fadeOut"
    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,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    button: {
    borderWidth: 2,
    margin: 2,
    padding: 5,
    backgroundColor: 'green',
    },
    container: {
    height: 400,
    },
    });
  5. Fausto95 revised this gist Dec 14, 2023. 6 changed files with 79 additions and 149 deletions.
    21 changes: 10 additions & 11 deletions App.js
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,18 @@
    import { useModals, ModalsIndexContextProvider } from './useModals';

    import { SafeAreaView, StyleSheet } from 'react-native';
    import RNModal from 'react-native-modal';
    import { useModals } from './useModals';

    function App_() {
    const Modal = useModals();

    return <SafeAreaView style={styles.container}>{Modal}</SafeAreaView>;
    }

    export default function App() {
    return (
    <SafeAreaView style={styles.container}>
    {Modal}
    </SafeAreaView>
    <ModalsIndexContextProvider>
    <App_ />
    </ModalsIndexContextProvider>
    );
    }

    @@ -19,10 +23,5 @@ const styles = StyleSheet.create({
    backgroundColor: '#ecf0f1',
    padding: 8,
    },
    paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    },
    });

    67 changes: 21 additions & 46 deletions Modal1.js
    Original file line number Diff line number Diff line change
    @@ -1,55 +1,30 @@
    import { useState, useCallback } from 'react';
    import Modal from 'react-native-modal';
    import { Text, StyleSheet, View, Pressable } from 'react-native';
    import { useState, useEffect } from 'react';
    import { Modal } from './Modal';

    export const Modal1 = ({ onModalHide }) => {
    const [isVisible, setIsVisible] = useState(true);
    const random = Math.floor(Math.random() * 3)
    const someHeavyCalculation = () => {
    const random = Math.floor(Math.random() * 3);
    if (random === 1) return Promise.resolve(true);
    return Promise.resolve(false);
    };

    if(random !== 1) {
    onModalHide();
    }
    export const Modal1 = ({ jumpToNextModal }) => {
    const [isVisible, setIsVisible] = useState(true);

    const onModalHide_ = useCallback(() => {
    onModalHide();
    }, [onModalHide]);
    useEffect(() => {
    someHeavyCalculation().then((result) => {
    if (result) {
    setIsVisible(result);
    } else {
    jumpToNextModal();
    }
    });
    }, [jumpToNextModal]);

    return (
    <Modal
    title="Modal 1"
    jumpToNextModal={jumpToNextModal}
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal1"
    style={styles.modal}

    animationOut="fadeOut"
    useNativeDriver
    onModalHide={onModalHide_}>
    <View style={styles.container}>
    <Text>Modal 1</Text>
    <Pressable onPress={onModalHide_}>
    <Text>Hide</Text>
    </Pressable>
    </View>
    </Modal>
    />
    );
    };

    const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    container: {
    height: 400,
    },
    });
    67 changes: 20 additions & 47 deletions Modal2.js
    Original file line number Diff line number Diff line change
    @@ -1,57 +1,30 @@
    import { useState, useCallback } from 'react';
    import Modal from 'react-native-modal';
    import { Text, StyleSheet, View, Pressable } from 'react-native';

    export const Modal2 = ({ onModalHide }) => {
    const [isVisible, setIsVisible] = useState(true);
    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);
    };

    if (random !== 1) {
    onModalHide();
    }


    export const Modal2 = ({ jumpToNextModal }) => {
    const [isVisible, setIsVisible] = useState(true);

    const onModalHide_ = useCallback(() => {
    onModalHide();
    }, [onModalHide]);
    useEffect(() => {
    someHeavyCalculation().then((result) => {
    if (result) {
    setIsVisible(result);
    } else {
    jumpToNextModal();
    }
    });
    }, [jumpToNextModal]);

    return (
    <Modal
    title="Modal 2"
    jumpToNextModal={jumpToNextModal}
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal2"
    style={styles.modal}
    animationOut="fadeOut"
    useNativeDriver
    onModalHide={onModalHide}>
    <View style={styles.container}>
    <Text>Modal 2</Text>
    <Pressable onPress={onModalHide_}>
    <Text>Hide</Text>
    </Pressable>
    </View>
    </Modal>
    />
    );
    };

    const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    container: {
    height: 400,
    },
    });
    60 changes: 21 additions & 39 deletions Modal3.js
    Original file line number Diff line number Diff line change
    @@ -1,49 +1,31 @@
    import { useState, useCallback } from 'react';
    import Modal from 'react-native-modal';
    import { Text, StyleSheet, View, Pressable } from 'react-native';
    import { useState, useEffect } from 'react';
    import { Modal } from './Modal';

    export const Modal3 = ({ onModalHide }) => {
    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);

    const onModalHide_ = useCallback(() => {
    onModalHide();
    }, [onModalHide]);
    useEffect(() => {
    someHeavyCalculation().then((result) => {
    if (result) {
    setIsVisible(result);
    } else {
    jumpToNextModal();
    }
    });
    }, [jumpToNextModal]);

    return (
    <Modal
    title="Modal 3"
    jumpToNextModal={jumpToNextModal}
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal3"
    style={styles.modal}
    animationOut="fadeOut"
    useNativeDriver
    onModalHide={onModalHide}>
    <View style={styles.container}>
    <Text>Modal 3</Text>
    <Pressable onPress={onModalHide_}>
    <Text>Hide</Text>
    </Pressable>
    </View>
    </Modal>
    />
    );
    };

    const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    container: {
    height: 400,
    },
    });
    5 changes: 4 additions & 1 deletion readme.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,6 @@
    ![image](https://gist.github.com/assets/23306911/da1b9960-bf56-4d2e-9294-071cd66835e4)

    The goal is to be as close to this
    The goal is to be as close to this as possible


    [Expo Snack Demo](https://snack.expo.dev/@fausto95/react-native-modal-queue)
    8 changes: 3 additions & 5 deletions useModals.js
    Original file line number Diff line number Diff line change
    @@ -17,8 +17,6 @@ export const ModalsIndexContext = createContext({
    export const ModalsIndexContextProvider = ({ children }) => {
    const [index, setIndex] = useState(0);

    console.log({ index });

    return (
    <ModalsIndexContext.Provider value={{ index, setIndex }}>
    {children}
    @@ -31,7 +29,7 @@ export const useModals = () => {

    const queue = useMemo(() => [() => Modal1, () => Modal2, () => Modal3], []);

    const onModalHide = useCallback(() => {
    const jumpToNextModal = useCallback(() => {
    setIndex((prev) => {
    const nextIndex = prev + 1;
    return nextIndex;
    @@ -40,12 +38,12 @@ export const useModals = () => {

    const CurrentModal = useMemo(() => {
    const queueLength = queue.length - 1;

    if (index > queueLength) return () => null;

    const Component = queue[index]();
    return Component;
    }, [queue, index]);

    return <CurrentModal onModalHide={onModalHide} />;
    return <CurrentModal jumpToNextModal={jumpToNextModal} />;
    };
  6. Fausto95 revised this gist Dec 14, 2023. 1 changed file with 9 additions and 11 deletions.
    20 changes: 9 additions & 11 deletions useModals.js
    Original file line number Diff line number Diff line change
    @@ -29,25 +29,23 @@ export const ModalsIndexContextProvider = ({ children }) => {
    export const useModals = () => {
    const { index, setIndex } = useContext(ModalsIndexContext);

    const [queue, updateQueue] = useState([
    () => Modal1,
    () => Modal2,
    () => Modal3,
    ]);
    const queue = useMemo(() => [() => Modal1, () => Modal2, () => Modal3], []);

    const onModalHide = useCallback(() => {
    setIndex((prev) => {
    const nextIndex = prev + 1;
    if(nextIndex > queue.length - 1) return 0
    return nextIndex;
    });
    }, [setIndex, queue.length]);
    }, [setIndex]);

    const CurrentModal = useMemo(() => {
    if (index > queue.length - 1) return undefined;
    console.log('herererer');
    return queue[index]();
    const queueLength = queue.length - 1;

    if (index > queueLength) return () => null;

    const Component = queue[index]();
    return Component;
    }, [queue, index]);

    return <CurrentModal onModalHide={onModalHide} />;
    };
    };
  7. Fausto95 created this gist Dec 14, 2023.
    28 changes: 28 additions & 0 deletions App.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    import { SafeAreaView, StyleSheet } from 'react-native';
    import RNModal from 'react-native-modal';
    import { useModals } from './useModals';

    function App_() {
    const Modal = useModals();

    return (
    <SafeAreaView style={styles.container}>
    {Modal}
    </SafeAreaView>
    );
    }

    const styles = StyleSheet.create({
    container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#ecf0f1',
    padding: 8,
    },
    paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    },
    });
    55 changes: 55 additions & 0 deletions Modal1.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    import { useState, useCallback } from 'react';
    import Modal from 'react-native-modal';
    import { Text, StyleSheet, View, Pressable } from 'react-native';

    export const Modal1 = ({ onModalHide }) => {
    const [isVisible, setIsVisible] = useState(true);
    const random = Math.floor(Math.random() * 3)

    if(random !== 1) {
    onModalHide();
    }

    const onModalHide_ = useCallback(() => {
    onModalHide();
    }, [onModalHide]);

    return (
    <Modal
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal1"
    style={styles.modal}

    animationOut="fadeOut"
    useNativeDriver
    onModalHide={onModalHide_}>
    <View style={styles.container}>
    <Text>Modal 1</Text>
    <Pressable onPress={onModalHide_}>
    <Text>Hide</Text>
    </Pressable>
    </View>
    </Modal>
    );
    };

    const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    container: {
    height: 400,
    },
    });
    57 changes: 57 additions & 0 deletions Modal2.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    import { useState, useCallback } from 'react';
    import Modal from 'react-native-modal';
    import { Text, StyleSheet, View, Pressable } from 'react-native';

    export const Modal2 = ({ onModalHide }) => {
    const [isVisible, setIsVisible] = useState(true);

    const random = Math.floor(Math.random() * 3);

    if (random !== 1) {
    onModalHide();
    }



    const onModalHide_ = useCallback(() => {
    onModalHide();
    }, [onModalHide]);

    return (
    <Modal
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal2"
    style={styles.modal}
    animationOut="fadeOut"
    useNativeDriver
    onModalHide={onModalHide}>
    <View style={styles.container}>
    <Text>Modal 2</Text>
    <Pressable onPress={onModalHide_}>
    <Text>Hide</Text>
    </Pressable>
    </View>
    </Modal>
    );
    };

    const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    container: {
    height: 400,
    },
    });
    49 changes: 49 additions & 0 deletions Modal3.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,49 @@
    import { useState, useCallback } from 'react';
    import Modal from 'react-native-modal';
    import { Text, StyleSheet, View, Pressable } from 'react-native';

    export const Modal3 = ({ onModalHide }) => {
    const [isVisible, setIsVisible] = useState(true);

    const onModalHide_ = useCallback(() => {
    onModalHide();
    }, [onModalHide]);

    return (
    <Modal
    isVisible={isVisible}
    hideModalContentWhileAnimating
    hasBackdrop
    backdropColor={'green'}
    backdropOpacity={0.75}
    testID="modal3"
    style={styles.modal}
    animationOut="fadeOut"
    useNativeDriver
    onModalHide={onModalHide}>
    <View style={styles.container}>
    <Text>Modal 3</Text>
    <Pressable onPress={onModalHide_}>
    <Text>Hide</Text>
    </Pressable>
    </View>
    </Modal>
    );
    };

    const styles = StyleSheet.create({
    modal: {
    padding: 0,
    margin: 0,
    backgroundColor: 'white',
    flex: 1,
    position: 'absolute',
    borderTopLeftRadius: 10,
    borderTopRightRadius: 10,
    width: '100%',
    bottom: 0,
    },
    container: {
    height: 400,
    },
    });
    10 changes: 10 additions & 0 deletions index.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    import { ModalsIndexContextProvider } from './useModals';
    import App_ from './App.js';

    export default function App() {
    return (
    <ModalsIndexContextProvider>
    <App_ />
    </ModalsIndexContextProvider>
    );
    }
    3 changes: 3 additions & 0 deletions readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    ![image](https://gist.github.com/assets/23306911/da1b9960-bf56-4d2e-9294-071cd66835e4)

    The goal is to be as close to this
    53 changes: 53 additions & 0 deletions useModals.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    import { Modal1 } from './Modal1';
    import { Modal2 } from './Modal2';
    import { Modal3 } from './Modal3';
    import {
    useState,
    useCallback,
    useMemo,
    useContext,
    createContext,
    } from 'react';

    export const ModalsIndexContext = createContext({
    index: 0,
    setIndex: () => undefined,
    });

    export const ModalsIndexContextProvider = ({ children }) => {
    const [index, setIndex] = useState(0);

    console.log({ index });

    return (
    <ModalsIndexContext.Provider value={{ index, setIndex }}>
    {children}
    </ModalsIndexContext.Provider>
    );
    };

    export const useModals = () => {
    const { index, setIndex } = useContext(ModalsIndexContext);

    const [queue, updateQueue] = useState([
    () => Modal1,
    () => Modal2,
    () => Modal3,
    ]);

    const onModalHide = useCallback(() => {
    setIndex((prev) => {
    const nextIndex = prev + 1;
    if(nextIndex > queue.length - 1) return 0
    return nextIndex;
    });
    }, [setIndex, queue.length]);

    const CurrentModal = useMemo(() => {
    if (index > queue.length - 1) return undefined;
    console.log('herererer');
    return queue[index]();
    }, [queue, index]);

    return <CurrentModal onModalHide={onModalHide} />;
    };