How to override the back button / sipe functionality in React Native

50 views Asked by At

I am trying to acheive overiding the back/swipe back functionality in react native.

If you land on a page and it has a param of previousScreen. Then this screen should be used to override the back functionality. Using navigation.navigate(previousScreen) to go to that screen.

Can somebody point me in the right direction?

The code below I'm trying gives me a maximum call stack error when clicked, I think its due to the dependencies in my useEffect but not sure:

  React.useEffect(() => {
    const handleBeforeRemove = e => {
      e.preventDefault();

      if (!previousScreen) {
        navigation.dispatch(e.data.action);
      } else {
        navigation.navigate(previousScreen);
      }
    };

    if (previousScreen) {
      const unsubscribe = navigation.addListener(
        'beforeRemove',
        handleBeforeRemove,
      );

      return unsubscribe;
    }
  }, [navigation, previousScreen]);

Tried like this also same error:

   const backAction = e => {
    e.preventDefault();

    if (previousScreen) {
      navigation.navigate(previousScreen);
      return;
    }

    if (!previousScreen) {
      navigation.dispatch(e.data.action);
      return true;
    }

    return;
  };

  useEffect(() => {
    navigation.addListener('beforeRemove', backAction);
    return () => {
      navigation.removeListener('beforeRemove', backAction);
    };
  }, []);
1

There are 1 answers

2
Pedro Borges Jr On

You can achieve that using the useBackHandler hook or not.

Using useBackHandler hook:

Make sure to install @react-native-community/hooks to use the useBackHandler hook.

import React from 'react';
import { View, Text } from 'react-native';
import { useBackHandler } from '@react-native-community/hooks';

const YourPage = ({ route, navigation }) => {
  const previousScreen = route?.params?.previousScreen || '';

  const handleBackPress = () => {
    if (previousScreen !== '') {
      navigation.replace(previousScreen);
      return true;
    }
    // If previousScreen is empty, perform default back action
    return false;
  };

  useBackHandler(handleBackPress);

  if (previousScreen === '') {
    return (
      <View>
        <Text>No specific back functionality available</Text>
      </View>
    );
  }

  return (
    // Your component's JSX
  );
};

export default YourPage;

Without using useBackHandler hook:

import React from 'react';
import { BackHandler, View, Text } from 'react-native';

const YourPage = ({route}) => {
  const previousScreen = route?.params?.previousScreen || '';

  const handleBackPress = () => {
      navigation.replace(previousScreen)
      return true;
  };

  useEffect(() => {
    if (previousScreen !== '') {
    BackHandler.addEventListener('hardwareBackPress', handleBackPress);
    }

    return () => {
      if (previousScreen !== '') {
      BackHandler.removeEventListener('hardwareBackPress', handleBackPress);
      }
    };
  }, [previousScreen]);

  return (
    // Your component's JSX
  );
};

Make sure to check https://github.com/react-native-community/hooks#usebackhandler if you decide to proceed if useBackHandler.