skip to Main Content

How do you make a modal pop-up without clicking a button in react native? I am currently using an alert to pop -up once the game state changes but I’d like to be able to style it so I want to change it to a modal view. I’m not sure how to implement it into my code 🙁 Could someone please teach me how?

  const checkGameState = () => {
    if (gameWon()) {
      setGameState('won')
      Alert.alert('You won!', [
        { text: 'play again', onPress: () => newGame() }
      ])
    } else if (gameLost()) {
      setGameState('lost')
      Alert.alert('You Lost', [
        { text: 'try again', onPress: () => newGame() }
      ])
    }
  }

3

Answers


  1. Use react-native-modalize for easy modals, this saved me alot of hours and pain.

    import React, { useRef } from 'react';
    import { Modalize } from 'react-native-modalize';
    
    const modal = useRef(null);
    
    const verifyBeforeSend = () => {
        modal.current?.open();
    }
    
    
    return (
        // your screen content
    
            <Modalize adjustToContentHeight ref={modal}>
    
            // your modal content
    
            </Modalize>
    
        // your screen content
    )
    

    I guess this is you were looking for

    Login or Signup to reply.
  2. You can create GlobalModal at App.js, using ref = createRef()
    when you want call it, you can call ref.current.open(…) everywhere

    Login or Signup to reply.
  3. You could use react native’s modal component to get your custom styling. You would need to create a context to be able to easily access the alert parameters, and then create a hook to update those parameters (demo):

    Context:

    import { createContext, useState, useEffect, useCallback } from 'react';
    import Alert from './components/Alert';
    // i like to handle all global context stuff in a single file
    // e.g. navigationcontainer, gesturehandler root view, etc
    
    export const AlertContext = createContext({
      title: '',
      message: '',
      buttons: [],
      visible: false,
      setAlertParams: () => {},
    });
    
    export default function ContextContainer({ children }) {
      const [alertParams, setAlertParams] = useState({
        title: '',
        message: '',
        buttons: [],
        visible: false,
      });
     
      return (
        <AlertContext.Provider
          value={{ ...alertParams, setAlertParams }}>
          <>
            {children}
            <Alert />
          </>
        </AlertContext.Provider>
      );
    }
    

    Alert Component:

    import { useContext } from 'react';
    import {
      View,
      StyleSheet,
      Text,
      Button,
      useWindowDimensions,
      Modal,
      FlatList,
    } from 'react-native';
    import { AlertContext } from '../Context';
    import ModalButton from './ModalButton'
    export default function Alert() {
      const {
        title,
        message,
        buttons,
        visible,
        setAlertParams,
        closeAlert
      } = useContext(AlertContext);
      const { width, height } = useWindowDimensions();
      const modalWidth = width * 0.8;
      const modalHeight = width * 0.8;
      
      return (
        <Modal visible={visible} transparent>
          <View
            style={[
              styles.modalContainer,
              {
                width: modalWidth,
                //height: modalHeight,
                top: height * 0.25,
                left: width * 0.1,
              },
            ]}>
            <Text style={styles.title}>{title}</Text>
            <View style={styles.messageView}>
              <Text style={styles.message}>{message}</Text>
            </View>
            <View
              style={[
                styles.buttonRowContainer,
                {
                  width: modalWidth - styles.modalContainer.padding * 2,
                },
              ]}>
              <FlatList
                style={{ flexDirection: 'row' }}
                contentContainerStyle={{
                  flexDirection: 'row',
                  justifyContent: 'space-between',
                }}
                data={buttons}
                horizontal
                renderItem={ModalButton}
              />
            </View>
          </View>
        </Modal>
      );
    }
    
    const styles = StyleSheet.create({
      modalContainer: {
        position: 'absolute',
        opacity: 1,
        backgroundColor: 'lightgreen',
        overflow: 'hidden',
        padding: 5,
        borderRadius: 15,
      },
      titleRow: {
        flexDirection: 'row',
        width: '100%',
        justifyContent: 'space-between',
      },
      buttonRowContainer: {
        marginVertical: 4,
      },
      title: {
        fontSize: 24,
        fontWeight: 'bold',
        textAlign: 'center',
      },
      message: {
        fontSize: 16,
      },
      messageView: {
        marginVertical: 5,
        padding: 5,
      },
    });
    

    Hook:

    import { useCallback, useContext } from 'react';
    import { AlertContext } from '../Context';
    
    export default function useAlert() {
      const { setAlertParams } = useContext(AlertContext);
      const closeAlert = useCallback(() => {
        setAlertParams((prev) => {
          return { ...prev, visible: false };
        });
      }, [setAlertParams]);
      const showAlert = useCallback(
        (title, message, buttons, hideCloseButton) => {
          buttons = buttons || [];
          if (buttons.length == 0) {
            buttons = [{ title: 'Ok', onPress: closeAlert }];
          }
          if (!hideCloseButton)
            buttons.push({ title: 'Cancel', onPress: closeAlert });
          setAlertParams({ title, message, buttons, visible: true });
        },
        [closeAlert, setAlertParams]
      );
      return { closeAlert, showAlert };
    }
    

    Usage:

    import {useContext} from 'react';
    import { Text, View, StyleSheet, Button } from 'react-native';
    import Constants from 'expo-constants';
    import {AlertContext} from '../Context'
    import useAlert from '../hooks/useAlert'
    const alertButtons = Array(3).fill(null).map((_,index)=>{
      const num = index+1
      return {
        title:"Button "+ num,
        onPress:()=>console.log("Button",num, "was pressed")
      }
    })
    
    export default function App() {
      const { showAlert, closeAlert } = useAlert();
      return (
        <View style={styles.container}>
            <Text>Just a normal screen</Text>
            <Button
              title="Open Alert"
              onPress={() =>
                showAlert(
                  'Testing alert',
                  'There should be a message in the alert',
                  alertButtons
                )
              }
            />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        paddingTop: Constants.statusBarHeight,
        backgroundColor: '#ecf0f1',
        padding: 8,
      },
      paragraph: {
        margin: 24,
        fontSize: 18,
        fontWeight: 'bold',
        textAlign: 'center',
      },
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search