react-native: iOS can't dismiss Modal!

Description

On iOS the <Modal> component cannot be dismissed by dragging down. (gesture is a native behaviour on iOS)

The reason for that being is that the onDismiss or onRequestClose function is never called. It is only being called on tvOS.

React Native version:

info Fetching system and libraries information...
(node:10129) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
System:
    OS: macOS 10.15.5
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
    Memory: 2.78 GB / 32.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 14.4.0 - /usr/local/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.14.5 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.9.3 - /usr/local/bin/pod
  SDKs:
    iOS SDK:
      Platforms: iOS 13.5, DriverKit 19.0, macOS 10.15, tvOS 13.4, watchOS 6.2
    Android SDK:
      API Levels: 25, 28, 29
      Build Tools: 28.0.3, 29.0.2, 29.0.3, 30.0.0, 30.0.0, 30.0.0
      System Images: android-29 | Google APIs Intel x86 Atom, android-29 | Google Play Intel x86 Atom
      Android NDK: 21.2.6472646
  IDEs:
    Android Studio: 4.0 AI-193.6911.18.40.6514223
    Xcode: 11.5/11E608c - /usr/bin/xcodebuild
  Languages:
    Java: 1.8.0_252 - /usr/bin/javac
    Python: 2.7.16 - /usr/bin/python
  npmPackages:
    @react-native-community/cli: Not Found
    react: 16.13.1 => 16.13.1 
    react-native: 0.63.0 => 0.63.0 
  npmGlobalPackages:
    *react-native*: Not Found

Steps To Reproduce

  1. Create <Modal> component and set visible and onRequestClose properties
  2. Open Modal by setting visible to true
  3. Try to close Modal by dragging down

Expected Results

Modal should be dragged down and onDismiss or onRequestClose should be called

Snack, code example, screenshot, or link to a repository:

<Modal
  presentationStyle="pageSheet"
  visible={true}
  onRequestClose={() => console.log("will never be called.")} />

Screen Recording 2020-07-09 at 13 40 49 mov

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 32
  • Comments: 19 (2 by maintainers)

Commits related to this issue

Most upvoted comments

Implemented the solution suggested by @alexandersandberg and it works!

Combine https://reactnavigation.org/docs/modal with https://stackoverflow.com/questions/62283000/is-it-possible-to-present-modals-with-the-uimodalpresentationpagesheet-or-uimoda

Here’s my code. You should be able to paste this in and have it work (assuming you have the correct dependencies)

import React from 'react'
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'

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

import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { enableScreens } from 'react-native-screens'

enableScreens()

const MainStack = createStackNavigator()
const RootStack = createNativeStackNavigator()

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 30 }}>This is the home screen!</Text>
      <Button
        onPress={() => navigation.navigate('MyModal')}
        title="Open Modal"
      />
    </View>
  )
}

function DetailsScreen() {
  return (
    <View>
      <Text>Details</Text>
    </View>
  )
}

function MainStackScreen() {
  return (
    <MainStack.Navigator>
      <MainStack.Screen name="Home" component={HomeScreen} />
      <MainStack.Screen name="Details" component={DetailsScreen} />
    </MainStack.Navigator>
  )
}

function ModalScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 30 }}>This is a modal!</Text>
      <Button onPress={() => navigation.goBack()} title="Dismiss" />
    </View>
  )
}

// We use React Navigation's modal to be able to use swipeable native modals
function RootStackScreen() {
  return (
    <RootStack.Navigator
      mode="modal"
      screenOptions={{
        headerShown: false,
        stackPresentation: 'formSheet'
      }}
    >
      <RootStack.Screen
        name="Main"
        component={MainStackScreen}
        options={{ headerShown: false }}
      />
      <RootStack.Screen
        name="MyModal"
        component={ModalScreen}
      />
    </RootStack.Navigator>
  )
}

export default function AppNavigator() {
  return (
    <NavigationContainer>
      <RootStackScreen />
    </NavigationContainer>
  )
}

Not a solution to this issue, but a perfectly working alternative for some:

React Navigation’s createNativeStackNavigator with a stackPresentation set to modal, formSheet, or whatever you prefer.

Edit: Some more information on how to implement a modal like this can be found in the React Navigation docs: Opening a full-screen modal.

Hi, is someone able to dismiss the modal with React Native 0.64? I upgraded, and this is not working for me…

I just tried with a brand new project and it’s not working. Here’s my example code:

import React, {useState} from 'react';
import {SafeAreaView, StatusBar, Text, Modal, Button} from 'react-native';

const App = () => {
  const [visible, setVisible] = useState(false);

  return (
    <SafeAreaView>
      <StatusBar barStyle="light-content" />
      <Button title="Open" onPress={() => setVisible(true)} />
      <Modal
        visible={visible}
        presentationStyle="pageSheet"
        animationType="slide"
        onRequestClose={() => {
          console.log('close');
          setVisible(false);
        }}
        onDismiss={() => {
          console.log('dismiss');
          setVisible(false);
        }}>
        <Text>Modal</Text>
      </Modal>
    </SafeAreaView>
  );
};

export default App;

Unfortunately, neither function is firing. Is there anything I missed? Everything is fine in react-native doctor, and I started the new project with react-native globally installed:

yarn global add react-native
react-native init ExampleProject

Then just changed the App.js.

Hi all, how about this issue, i still find this issue on RN. 0.63.4

Any updates on this issue? I’m on 0.72 and I still see the issue.

This patch works for me react-native+0.63.3.patch