From 6d518a46b89496f4a3bfd2da24245fe344f97290 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 28 Jul 2021 15:31:27 +0200 Subject: [PATCH] fix: show error when beforeRemove is used to prevent action in naive stack --- example/src/Screens/PreventRemove.tsx | 10 +++------- .../src/views/NativeStackView.tsx | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/example/src/Screens/PreventRemove.tsx b/example/src/Screens/PreventRemove.tsx index 19a07488..f917b0db 100644 --- a/example/src/Screens/PreventRemove.tsx +++ b/example/src/Screens/PreventRemove.tsx @@ -1,6 +1,5 @@ import { CommonActions, - NavigationAction, ParamListBase, useTheme, } from '@react-navigation/native'; @@ -69,10 +68,7 @@ const InputScreen = ({ React.useEffect( () => navigation.addListener('beforeRemove', (e) => { - const action: NavigationAction & { payload?: { confirmed?: boolean } } = - e.data.action; - - if (!hasUnsavedChanges || action.payload?.confirmed) { + if (!hasUnsavedChanges) { return; } @@ -84,7 +80,7 @@ const InputScreen = ({ ); if (discard) { - navigation.dispatch(action); + navigation.dispatch(e.data.action); } } else { Alert.alert( @@ -95,7 +91,7 @@ const InputScreen = ({ { text: 'Discard', style: 'destructive', - onPress: () => navigation.dispatch(action), + onPress: () => navigation.dispatch(e.data.action), }, ] ); diff --git a/packages/native-stack/src/views/NativeStackView.tsx b/packages/native-stack/src/views/NativeStackView.tsx index 23ac983a..f7931b25 100644 --- a/packages/native-stack/src/views/NativeStackView.tsx +++ b/packages/native-stack/src/views/NativeStackView.tsx @@ -93,6 +93,24 @@ type Props = { }; function NativeStackViewInner({ state, navigation, descriptors }: Props) { + const [nextDismissedKey, setNextDismissedKey] = + React.useState(null); + + const dismissedRouteName = nextDismissedKey + ? state.routes.find((route) => route.key === nextDismissedKey)?.name + : null; + + React.useEffect(() => { + if (dismissedRouteName) { + const message = + `The screen '${dismissedRouteName}' was removed natively but didn't get removed from JS state. ` + + `This can happen if the action was prevented in a 'beforeRemove' listener, which is not fully supported in native-stack.\n\n` + + `Consider using 'gestureEnabled: false' to prevent back gesture and use a custom back button with 'headerLeft' option to override the native behavior.`; + + console.error(message); + } + }, [dismissedRouteName]); + return ( {state.routes.map((route, index) => { @@ -173,6 +191,8 @@ function NativeStackViewInner({ state, navigation, descriptors }: Props) { source: route.key, target: state.key, }); + + setNextDismissedKey(route.key); }} >