I'm using react navigation in a react native project and i am unable to find how to go back to navigation root (first screen in app) from an arbitrary screen. Navigation is like this:
<NavigationContainer>
<Stack.Navigator>
{!loggedIn ? (
// Login
<Stack.Group>
<Stack.Screen name="LogInScreen" component={LogInScreen} />
</Stack.Group>
) : (
// App Screens
<Stack.Group>
// This Tab navigator may have more stacks inside
<Stack.Screen name="AppTabsNavigator" component={AppTabsNavigator} />
<Stack.Screen name="SomeErrorOutsideTabs" component={SomeErrorOutsideTabs} />
</Stack.Group>
)}
// Error Modals
<Stack.Group>
<Stack.Screen name="SomeErrorScreen" component={SomeErrorScreen} />
</Stack.Group>
<Stack.Navigator>
</NavigationContrainer>
Use cases are:
User in
LogInScreencauses some error ->SomeErrorScreenshows -> User press button to go back toLogInScreen.User in anywhere else causes some error ->
SomeErrorScreenshows -> User press button to go back to first screen inAppTabsNavigator(sometimes does not work depending on inner stacks).
The summary is, no matter where you are, when you press button in SomeErrorScreen you must go back to "first app screen", which is LogInScreen if not logged in or first tab of AppTabsNavigator if logged in.
I have tried using popToTop() but it does not work when there are inners Stacks like SomeResourceStack inside AppTabsNavigator to contain index and show of resource, for example:
User in AppTabsNavigator > SomeResourceStack > index access to AppTabsNavigator > SomeResourceStack > show, cause SomeErrorScreen to appear and when going back, he goes back to AppTabsNavigator > SomeResourceStack > show instead of AppTabsNavigator first tab.
Answer:
The right answer is to use reset like Anthony Marino said and combine it with Ararat Ispiroglu suggestion. I controlled Android's back button behavior as well:
...
import { BackHandler } from 'react-native'
import { useFocusEffect } from '@react-navigation/native'
import { useSelector } from 'react-redux'
...
const SomeErrorScreen = ({ navigation }) => {
...
const loggedIn = useSelector(state => state.auth.loggedIn)
const onGoingBackButtonPress = React.useCallback(() => {
navigation.reset({
index: 0,
routes: [{ name: !loggedIn ? 'LogInScreen' : 'AppTabsNavigator' }]
})
}, [navigation, loggedIn])
const androidBackButtonCallback = React.useCallback(() => {
const onBackPress = () => {
onGoingBackButtonPress()
return true
}
BackHandler.addEventListener('hardwareBackPress', onBackPress)
return () => BackHandler.removeEventListener('hardwareBackPress', onBackPress)
}, [onGoingBackButtonPress])
useFocusEffect(androidBackButtonCallback)
...
return <View>
<Button onPress={onGoingBackButtonPress } />
</View>
}
export default SomeErrorScreen