how to override behaviour of backButton on react native navigation

I am using https://wix.github.io/react-native-navigation/docs/before-you-start/ for navigation for my react native app. I have one issue where let say there are three cmp A,B,C. From comp A there is a history.push() executed which redirect to cmp B and then cmp B is some path matcher where renders particular component based on the path pushed from A, let say cmp B matches the path and than it renders C cmp, where C has smth like this:

Code:

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

So the C cmp pushes a new screen to the stack, so at this moment when clicking back from the navigation I would like to instead redirect me to A and not B. How can I change the behaviour of back button or can I disable it somehow? pressing back button redirects me back to cmp B currently and I dont want to!

Thank you.

Answer

You can change the behavior when going back by using navigation.addListener(). I found it a little clunky but it works – in our case we warn on going back if data would be lost. We also had to distinguish between Save and Back presses, which we did by setting a state flag when Save button was pressed. Here’s what the hook looks like – I think it should be adaptable to your needs:

// 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: () => {} },
  ]);
}