software-mansion / react-native-screens

Native navigation primitives for your React Native app.
MIT License
2.86k stars 484 forks source link

[iOS] back gesture activates `Pressable` element #2118

Closed kirillzyusko closed 2 days ago

kirillzyusko commented 2 weeks ago

Description

If your Pressable "touches" the border of the screen and you do a back gesture on iOS, then after finger releasing this Pressable will be activated.

A difference between native-stack and stack:

Stack Native-Stack

The issue can be reproducible in RNS example app, so I'm just posting a code sample instead of providing a full reproduction repo (let me know if it's not sufficient - I'll post full reproduction example then).

import React, { useEffect } from 'react';
import {View, Text, Button, Pressable, StyleSheet, Alert} from 'react-native';
import {GestureHandlerRootView} from 'react-native-gesture-handler';

const fill = {flex: 1};

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

function HomeScreen({navigation}) {
    return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
            <Text>Home Screen</Text>
            <Button
                title="Go to Details"
                onPress={() => navigation.navigate('DetailsStack')}
            />
        </View>
    );
}

const styles = StyleSheet.create({
    wrapperCustom: {
        width: "100%",
        height: 100,
        marginHorizontal: 30,
        borderRadius: 10,
        margin: 10,
    },
    text: {
        fontSize: 20,
        color: 'black',
    },
});

function DetailsScreen({ navigation }) {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        {new Array(10).fill(0).map((_, i) => (
          <Pressable
            onPress={() => {
                Alert.alert('Pressed!');
            }}
            style={({pressed}) => [
                {
                backgroundColor: pressed ? 'rgb(210, 230, 255)' : 'white',
                },
                styles.wrapperCustom,
            ]}>
            {({pressed}) => (
                <Text style={styles.text}>{pressed ? 'Pressed!' : 'Press Me'}</Text>
            )}
            </Pressable>
        ))}
      </View>
    );
  }

const Stack = createNativeStackNavigator(); // <-- change to createStackNavigator to see a difference

function App() {
    return (
        <GestureHandlerRootView style={fill}>
            <NavigationContainer>
                <Stack.Navigator screenOptions={{animation: 'slide_from_left'}}>
                    <Stack.Screen name="Home" component={HomeScreen} />
                    <Stack.Screen name="DetailsStack" component={DetailsScreen} />
                </Stack.Navigator>
            </NavigationContainer>
        </GestureHandlerRootView>
    );
}

export default App;

Steps to reproduce

  1. go to details screen
  2. swipe from left
  3. release a finger

Expected result

Alert shouldn't be shown

Actual result

Alert is shown

Snack or a link to a repository

https://github.com/software-mansion/react-native-screens

Screens version

3.31.0

React Native version

0.73.4

Platforms

iOS

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Fabric (New Architecture)

Build type

Debug mode

Device

iOS simulator

Device model

iPhone 15 Pro (iOS 17.4)

Acknowledgements

Yes

github-actions[bot] commented 2 weeks ago

Hey! 👋

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

kkafar commented 2 weeks ago

Good catch & thanks for report! Can confirm it happens.