如何在反应本机导航时覆盖后退按钮的行为

how to override behaviour of backButton on react native navigation

我正在使用 https://wix.github.io/react-native-navigation/docs/before-you-start/ 为我的 React 本机应用程序导航。我有一个问题,假设有三个 cmp A、B、C。从 comp A 执行 history.push() 重定向到 cmp B 然后 cmp B 是一些路径匹配器,其中根据从 A 推送的路径渲染特定组件,假设 cmp B 匹配路径并且比它渲染C cmp,其中 C 有这样的东西:

代码:

              Navigation.push(componentId, {
                component: {
                    id: 'BottomSheetRollupView',
                    name: 'bottomSheet.Rollup',
                    passProps: {
                        component,
                        passProps,
                    },
                    options: {
                        statusBar: {
                            style: Platform.select({android: 'light', ios: 'dark'}),
                        },
                    },
                },
            });

所以 C cmp 将一个新屏幕推送到堆栈,所以此刻当从导航中单击返回时,我想改为将我重定向到 A 而不是 B。如何更改后退按钮的行为或我可以以某种方式禁用它吗?按后退按钮会将我重定向回 cmp B,我不想!

谢谢。

您可以使用 navigation.addListener() 更改返回时的行为。我发现它有点笨拙,但它确实有效——在我们的例子中,如果数据丢失,我们会警告返回。我们还必须区分 Save 和 Back 按下,这是通过在按下 Save 按钮时设置状态标志来实现的。挂钩的外观如下 - 我认为它应该可以适应您的需求:

// Based on: https://reactnavigation.org/docs/preventing-going-back/
function useAlertOnGoBack({
  hasEdited,
  didSave,
}: {
  hasEdited: boolean;
  didSave: boolean;
}) {
  const navigation = useNavigation();
  useEffect(() => {
    const unsubscribe = navigation.addListener("beforeRemove", e => {
      if (!hasEdited || didSave) {
        // No listener
        return;
      }

      // Prevent default behavior of leaving the screen
      e.preventDefault();

      showExitWithoutSavingAlert(() => navigation.dispatch(e.data.action));
    });

    return unsubscribe;
  }, [hasEdited, navigation, didSave]);
}

export function showExitWithoutSavingAlert(dismissScreen: () => void) {
  // Prompt the user before leaving the screen
  Alert.alert("Discard unsaved changes?", undefined, [
    {
      text: "Discard Changes",
      style: "destructive",
      // If the user confirmed, then we dispatch the action we blocked earlier
      // This will continue the action that had triggered the removal of the screen
      onPress: dismissScreen,
    },
    { text: "Cancel", style: "cancel", onPress: () => {} },
  ]);
}