Prevent the going back on React Native
The Problem:
You may have gotten yourself in a situation where the user has concluded something and you do not want them to go back and do the same thing again.
In this article, we are going to be using Expo and Expo Go. We are also going to be using the Native Stack navigation to keep things simple.
Project Setup
In your terminal, run:
npx create-expo-app no-back-app --template blankThen:
cd no-back-appNext run:
npm install @react-navigation/native @react-navigation/native-stackSince we are using Expo, we now run:
npx expo install react-native-screens react-native-safe-area-contextFinally run:
npx expo startOn your device, use the Expo Go app to scan the barcode that appears in the terminal.
In the root folder now created, go to the “App.js” file. It should look something like this:
Creating Screens
Still in the root folder, create a new folder and name it “screens”. This is where the screens we are navigating through will be.
Get Charles’s stories in your inbox
Join Medium for free to get updates from this writer.
In the “screens” folder, create two files: “Home.js” and “Settings.js”. Paste the following code in Home.js:
import { View, Text } from "react-native"
const Home = () => {
return(
<View style={{height:'100%',display:'flex', justifyContent:'center', alignItems:'center'}}>
<Text>Home Screen</Text>
</View>
)
}
export default Home;In Settings.js, paste:
import { View, Text } from "react-native"
const Settings = () => {
return(
<View style={{height:'100%',display:'flex', justifyContent:'center', alignItems:'center'}}>
<Text>Settings Screen</Text>
</View>
)
}
export default Settings;Back to our App.js file, replace the code there with this:
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
const App = ()=> {
return (
<NavigationContainer>
</NavigationContainer>
);
}
export default App;Now import your Home and Settings screen to make your code look like this:
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import Home from './screens/Home';
import Settings from './screens/Settings';
const Stack = createNativeStackNavigator();
const App = ()=> {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name='Home' component={Home}/>
<Stack.Screen name='Settings' component={Settings}/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;On your expo Go, your screen should look like this:
Back to our Home screen, let’s bring in our navigation and a button to navigate. We modify our code to look like this:
import { useNavigation } from "@react-navigation/native";
import { View, Text, Button } from "react-native"
const Home = () => {
const navigation = useNavigation();
return(
<View style={{height:'100%',display:'flex', justifyContent:'center', alignItems:'center'}}>
<Text>Home Screen</Text>
<Button
title="Go to Settings"
onPress={()=> navigation.navigate('Settings')}
/>
</View>
)
}
export default Home;On our device, when we click on the button, we are navigated to the Settings page. It should look like this:
If we hit the back button, we are taken back to the home screen. This is not what we want. We don’t want to go back.
Solution:
In our Settings screen, we are going to add the navigation and attach an event listener to it. We modify our code to look like this:
import { useNavigation } from "@react-navigation/native";
import { useEffect } from "react";
import { View, Text } from "react-native"
const Settings = () => {
const navigation = useNavigation();
useEffect(() => {
//this is triggered if the screen is to be removed from view
navigation.addListener('beforeRemove', (e) => {
console.log(e.data)
if (e.data.action.type === "GO_BACK") {
// this prevents the action from happening
// i.e stops the screen from going back
e.preventDefault();
}
});
}, []);
return(
<View style={{height:'100%',display:'flex', justifyContent:'center', alignItems:'center'}}>
<Text>Settings Screen</Text>
</View>
)
}
export default Settings;On Android, if we try to go back with your phone’s back button, nothing happens. However, if we tap on the back button in the Header (both in Android and IOS), it still goes back.
Ugh frustrating.
So what is happening?
If you console log “e.data”, it will give you insight to what is happening. For the normal back we tried earlier, this is what we get in the console:
{"action": {"type": "GO_BACK", Symbol(VISITED_ROUTE_KEYS): Set {"Settings--hlQeXgwHiWrIj-4d0IBM"}}}You can see we are looking for the “type” that is “GO_BACK”.
However, for the back button in the header, this is what we get:
{"action": {"payload": {"count": 1}, "source": "Settings-Pgku2YtAfEcOerPVVWr0B", "target": "stack-wVPj-HjfLNpZnMhyAPoS3", "type": "POP", Symbol(VISITED_ROUTE_KEYS): Set {"Settings-Pgku2YtAfEcOerPVVWr0B"}}}You can see it is a bit different. Here, the “type” is “POP”. This is where the issue is.
To accommodate this, we modify our code in the “UseEffect” to look like this:
useEffect(() => {
//this is triggered if the screen to be removed from view
navigation.addListener('beforeRemove', (e) => {
if (e.data.action.type === "GO_BACK" || e.data.action.type === "POP") {
// this prevents the action from happening
e.preventDefault();
}
});
}, []);Now, if we hit the back button in the header, nothing happens.
Great!!! Mischief averted.
If you have gotten here, thank you so much and do leave a clap.







