Comparing React Native Modal and React Navigation Modal

Introduction

Recently at work, my colleagues engaged in a discussion about whether to use React Native Modal or React Navigation Modal. In our tech stack, we already have both integrations, so there's no extra work required for setup. I never thought of this before, particularly during my earlier experience at Shopee. We didn't use React Navigation, as we had our own internal navigation solution and UI SDK. Before my time at Shopee, React Navigation was the version 4.x, which only offered a full Modal solution. In this article, we will explore both implementations with actual code examples. Let's get started!

React Native Modal

// TransparentModal.js
import React, { useState } from 'react';
import { View, Modal, TouchableOpacity, Text, StyleSheet } from 'react-native';
import Modal from 'react-native-modal';
import styles from './styles';

const TransparentModal = ({ isVisible, closeModal }) => {
  return (
    <Modal
      isVisible={isVisible}
      animationIn="fadeIn"
      animationOut="fadeOut"
      backdropOpacity={0.5} // Adjust the opacity for transparency
      onBackdropPress={closeModal}
      style={styles.modalContainer}
    >
      <View style={styles.modalContent}>
        <Text>Modal Content</Text>
        <TouchableOpacity onPress={closeModal}>
          <Text>Close</Text>
        </TouchableOpacity>
      </View>
    </Modal>
  );
};

export default TransparentModal;
// HomeScreen.js
const HomeScreen = () => {
  const [isModalVisible, setIsModalVisible] = useState(false);

  const openModal = () => { setIsModalVisible(true) };
  const closeModal = () => { setIsModalVisible(false) };

  return (
    <View>
      {/** your other UI component */}
      <TouchableOpacity onPress={openModal}>
        <Text>Show Modal</Text>
      </TouchableOpacity>
      <TransparentModal isVisible={isModalVisible} closeModal={closeModal} />
    </View>
  );
};

export default HomeScreen;

The above is the base pseudo code of what a React Native Modal implementation would look like.

If you want to implement page view event tracking for the Modal, one potential method is to use the onLayout function to trigger your tracking event. Avoid using the page mount event for this purpose, as it may lead to unexpected behavior. (A React Native Modal is always rendered, it's just hidden on the component you included it on.) You want your Modal to send tracking events only when it is visible to the user. Therefore, it is not suitable to do so in a page mount event, such as useEffect(() => {}, []).

If you plan to add deep linking and triggering modal to open when landing on the Screen Page, one approach is to pass the navigation parameter to the HomeScreen Page and implement additional logic to set isModalVisible to true. Implementation could be various depending on your navigation solution.

React Navigation Modal

// HomeScreen.js
import React from 'react';
import { View, Text, Button } from 'react-native';

function HomeScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text>Home Screen</Text>
      <Button
        title="Open Modal"
        onPress={() => navigation.navigate('ModalScreen')}
      />
    </View>
  );
}

export default HomeScreen;
// ModalScreen.js

import React from 'react';
import { View, Text, Button } from 'react-native';

function ModalScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text>Modal Screen</Text>
      <Button
        title="Close Modal"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

export default ModalScreen;
// Navigation Stack

<NavigationContainer>
    <Stack.Navigator initialRouteName="Home">
       <Stack.Screen name="Home" component={HomeScreen} />
       <Stack.Screen
         name="ModalScreen"
         component={ModalScreen}
         options={{
          presentation: 'transparentModal',
         }}
        />
    </Stack.Navigator>
</NavigationContainer>

The above is the base code of what a React Navigation Modal implementation would look like.

To implement the Deep link, add configs to the NavigationContainer.

const linking = {
  prefixes: ['example://', 'https://example.com'],
  config: { screens: { ModalScreen: 'modal' } }
};

 <NavigationContainer linking={linking}>
    {/* content */}
 </NavigationContainer>

This will link example://modal or https://example.com/modal, to your desired modal.

Conclusion

In this article, we explored the implementations of React Native Modal and React Navigation Modal with code examples. Choosing between them always depends on your use case. If you are building a simple modal on a page level, then go with the React Native Modal to keep things simple. If you want to create multiple modals in different parts of the application that behave similarly, and potentially integrate deep links with these modals, then opting for React Navigation will provide an easier setup. In the end, decisions are all about trade-offs.


Thank you for reading this far. If you found this article helpful or learned something new, please consider showing your support by liking it and following me for updates on future posts.
✨Stay tuned! ✨