使用 expo-router 时防止默认后退导航

Tho*_*ötz 6 react-native react-navigation expo stack-navigator

我目前是第一次使用 expo 和 expo-router,并对默认后退导航有疑问。我的意思是,例如,在 Google Pixel 上从屏幕左边缘滑动到屏幕中间。这将触发我的堆栈导航器上的后退导航。

在我之前使用 React Navtive CLI 和 React Navigation 的项目中,我可以通过向导航道具的“beforeRemove”事件添加事件侦听器来防止这种情况发生。

如何使用 expo-router 实现这一目标?我按照他们的指示构建了一个CustomStack 导航器,并希望我可以通过这种方式访问​​“导航”。我的代码基本上是这样的:

自定义堆栈.tsx

import { createStackNavigator, StackNavigationOptions } from "@react-navigation/stack";
import { withLayoutContext } from "expo-router";

const { Navigator } = createStackNavigator();

export const CustomStack = withLayoutContext<StackNavigationOptions, typeof Navigator>(Navigator);
Run Code Online (Sandbox Code Playgroud)

_layout.tsx

import { Stack } from "expo-router";
import { CustomStack } from "./CustomStack";

export default function RootLayout() {
return (
    <CustomStack>
        <Stack.Screen name="Home" />
        <Stack.Screen name="About" />
// ...
    </CustomStack>
  );
}
Run Code Online (Sandbox Code Playgroud)

关于.tsx

import type { StackScreenProps } from "@react-navigation/stack";
import { useEffect } from 'react';

export default function About({ navigation }: StackScreenProps<{}>) {

useEffect(() => {
   navigation.addListener('beforeRemove', (e) => {
        e.preventDefault();
        Alert.alert(
          'Changes might be lost',
          'Really want to go back?',
          [
            { text: "Cancel", style: 'cancel', onPress: () => { } },
            {
              text: "Yes",
              style: 'destructive',
              onPress: () => navigation.dispatch(e.data.action),
            },
          ]
        );
      };
    });
  }, [navigation]);
Run Code Online (Sandbox Code Playgroud)

在我的没有 TypeScript 的 RN CLI 应用程序中,About.jsx 中的 useEffect 有效。我可能搞乱了类型吗?我第一次将 TypeScript 与 RN 结合使用,并遵循了此文档

我真的很喜欢 expo-router 的方法,它根据我的文件定义导航路线,并且可以将布局文件添加到我的文件夹中。因此,如果有人能够解释如何防止默认的后退导航,同时仍然能够使用 expo-router,那就太棒了。

谢谢你的帮助,
托马斯

我尝试使用导航属性附加事件并阻止默认的后退导航。我创建了一个 CustomStack 导航器并根据文档导入了所有类型。我期望能够访问功能组件中的导航属性并向其添加事件侦听器。然而该属性是未定义的。

Ale*_*exy 5

无需为此使用自定义堆栈。解决方案要简单得多,因为您只需要使用 expo 中的导航,而不是像您那样使用反应本机导航。

因此,您可以使用 expo-router 堆栈并更新您的 About 组件,如下所示:

import { useNavigation } from 'expo-router';
import { useEffect } from 'react';

export default function About() {

    // Navigation
    const navigation = useNavigation();

    // Effect
    useEffect(() => { 
        navigation.addListener('beforeRemove', (e) => {
            e.preventDefault();
            console.log('onback');
            // Do your stuff here
            navigation.dispatch(e.data.action);
        });
    }, []);

}
Run Code Online (Sandbox Code Playgroud)

希望这会有所帮助,expo-router 文档目前还不完整。

请记住,您将管理侦听器以防止意外调用侦听器,例如使用removeListener。

  • 多谢。我不敢相信我在检查文档时错过了这一点:-)也许是给未来读者的一个快速的一般建议:addListener 函数返回一个清理回调,应该在 useEffect 的 return 语句中调用它。它与这个问题中的短代码片段并不真正相关,但如果您的依赖数组中有更多参数,那么这是必要的。 (3认同)