Resetting the navigation stack for the home screen (React Navigation and React Native)

JavascriptReact NativeNavigationReact Navigation

Javascript Problem Overview


I've got a problem with the navigation of React Navigation and React Native. It is about resetting navigation and returning to the home screen.

I've build a StackNavigator inside of a DrawerNavigator, and the navigation between home screen and other screens is working. But the problem is, that the navigation stack grows and grows. I'm not sure how to remove a screen from the stack.

For example when going from the home screen to the settings screen, then to the entry screen and lastly again to the home screen, the home screen is twice in the stack. With the back button I do not get out of the app, but again to the entry screen.

When selecting the home button again a reset of the stack would be great, but I don't know how to do this. Here someone tried to help an other person with a similar problem, but the solution didn't work for me.

const Stack = StackNavigator({
  Home: {
    screen: Home
  },
  Entry: {
    screen: Entry
  },
  Settings: {
    screen: Settings
  }
})

export const Drawer = DrawerNavigator({
  Home: {
    screen: Stack
  }},
  {
    contentComponent: HamburgerMenu
  }
)

And this is a simple example of the drawer screen

export default class HamburgerMenu extends Component {
  render () {
    return <ScrollView>
      <Icon.Button
        name={'home'}
        borderRadius={0}
        size={25}
        onPress={() => { this.props.navigation.navigate('Home')}}>
        <Text>{I18n.t('home')}</Text>
      </Icon.Button>

      <Icon.Button
        name={'settings'}
        borderRadius={0}
        size={25}
        onPress={() => { this.props.navigation.navigate('Settings')}}>
        <Text>{I18n.t('settings')}</Text>
      </Icon.Button>

      <Icon.Button
        name={'entry'}
        borderRadius={0}
        size={25}
        onPress={() => { this.props.navigation.navigate('Entry')}}>
        <Text>{I18n.t('entry')}</Text>
      </Icon.Button>
    </ScrollView>
  }
}

I hope you can help me. This is an essential part of the navigation and a solution would be great!

Javascript Solutions


Solution 1 - Javascript

React Navigation 5.x , 6.x

import { CommonActions } from '@react-navigation/native';

navigation.dispatch(
  CommonActions.reset({
    index: 1,
    routes: [
      { name: 'Home' },
      {
        name: 'Profile',
        params: { user: 'jane' },
      },
    ],
  })
);

Available in Snack

Solution 2 - Javascript

This is How I do it :

reset(){
    return this.props
               .navigation
               .dispatch(NavigationActions.reset(
                 {
                    index: 0,
                    actions: [
                      NavigationActions.navigate({ routeName: 'Menu'})
                    ]
                  }));
  }

at least replace 'Menu' with 'Home'. You may also want to adapt this.props.navigation to your implementation.

> In version > 2 follow this:

import { NavigationActions, StackActions } from 'react-navigation';
        const resetAction = StackActions.reset({
                index: 0,
                actions: [NavigationActions.navigate({ routeName: 'MainActivity' })],
            });
   
this.props.navigation.dispatch(resetAction); 

Solution 3 - Javascript

I found this way to go while using @react-navigation Bashirpour's Answer. However, while trying out Functional components where you already have navigation in props here is a neat way to write reset Stack action:

props.navigation.reset({
     index: 0,
     routes: [{ name: 'Dashboard' }]
})

Solution 4 - Javascript

Here is how I do it:

import { NavigationActions } from 'react-navigation'

this.props.navigation.dispatch(NavigationActions.reset({
    index: 0,
    key: null,
    actions: [NavigationActions.navigate({ routeName: 'ParentStackScreen' })]
}))

> The important part is key: null.

That wipes the stack while navigating from a child navigator to a parent navigator.

Do that if you get this error:

enter image description here

For animations, I use

// https://github.com/oblador/react-native-animatable
import * as Animatable from 'react-native-animatable'

I just control all the animations myself. Put them on any component you want by wrapping it with <Animatable.View>.

Solution 5 - Javascript

For newest versions of react-navigation you should use StackActions for reset the stack, here's a piece of code:

// import the following
import { NavigationActions, StackActions } from 'react-navigation'

// at some point in your code
resetStack = () => {
 this.props
   .navigation
   .dispatch(StackActions.reset({
     index: 0,
     actions: [
       NavigationActions.navigate({
         routeName: 'Home',
         params: { someParams: 'parameters goes here...' },
       }),
     ],
   }))
}

Solution 6 - Javascript

In React Navigation Versions 5.x

You can use StackActions.replace in this version

import { StackActions } from '@react-navigation/native';


navigation.dispatch(
    StackActions.replace('Home', { test: 'Test Params' })
)

ā€Œ

Full Example: (Available in Snack)
import * as React from 'react';
import { View, Button, Text } from 'react-native';
import { NavigationContainer, StackActions } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

function SplashScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{fontSize:25,marginBottom:25}} >SPLASH SCREEN!</Text>
      <Button
        title="Replace (RESET) with Home"
        onPress={() =>
          navigation.dispatch(
            StackActions.replace('Home', { test: 'Test Params' })
          )
        }
      />
      <View style={{margin:10}}/>
      <Button
        title="Push Home on the stack"
        onPress={() =>
          navigation.dispatch(StackActions.push('Home', { test: 'Test Params' }))
        }
      />
    </View>
  );
}

function HomeScreen({ navigation, route }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{fontSize:25,marginBottom:25}}>Home Screen!</Text>

      <Text style={{margin:10}}>{route.params.test}</Text>

      <Button
        title="Push same screen on the stack"
        onPress={() => navigation.dispatch(StackActions.pop(1))} 
      /> 
      <View style={{margin:10}}/>
      <Button
        title="Pop one screen from stack" 
        onPress={() =>
          navigation.dispatch(StackActions.push('Home', { test: 'Test Params' }))
        }
      />
      <View style={{margin:10}}/>
      <Button
        title="Pop to top" 
        onPress={() => navigation.dispatch(StackActions.popToTop())}
      />
    </View>
  );
}

const Stack = createStackNavigator();

export default function App() { 
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Splash" component={SplashScreen} />
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Solution 7 - Javascript

To use Back, you need to find the unique key associated with the path. Inside your navigation reducer, you can search the existing state to find the first route on the stack using that path, grab its key & pass that to Back. Back will then navigate to the screen prior to the path you gave.

  let key;

  if (action.payload) {
    // find first key associated with the route
    const route = action.payload;

    const routeObj = state.routes.find( (r) => r.routeName === route );

    if (routeObj) {
      key = { key: routeObj.key };
    }
  }

  return AppNavigator.router.getStateForAction( NavigationActions.back( key ), state );

Solution 8 - Javascript

NavigationActions.reset() seems to be the preferable solution. One issue I ran into with it actions was the tab buttons. Tabs would still show even if I explicitly turned them off in component. If I used navigation.navigate() instead of doing this via reset() it would work fine.

SomeComponentScreen.navigationOptions = {
  header: null
};

A workaround for this annoyance that worked for me is to consecutively call multiple navigate statements.

      navigation.goBack();   // this would pop current item in stack
      navigation.navigate({
        routeName: 'SomeOtherComponent'
      });

Solution 9 - Javascript

The Answer is createSwitchNavigator, it those not stack up your navigation. Add your auth screen/navigator in a createSwitchNavigator with the home screen/stack.

With that, when you navigate from home to log in, the stacks are not kept.

For more on it https://reactnavigation.org/docs/en/auth-flow.htmlLoginStack

Solution 10 - Javascript

The pop action takes you back to a previous screen in the stack. The n param allows you to specify how many screens to pop back by.

n - number - The number of screens to pop back by.

import { StackActions } from 'react-navigation';

const popAction = StackActions.pop({ n: 1, });

this.props.navigation.dispatch(popAction);

Solution 11 - Javascript

Just mix the two solutions given above and this will work just fine, basically we have to use StackActions and key: null. Without using StackActions, it was throwing some error

import { NavigationActions, StackActions } from 'react-navigation';
const resetHandler = () => {
        props.navigation.dispatch(StackActions.reset({
            index: 0,
            key: null,
            actions: [NavigationActions.navigate({ routeName: 'PatientDetails' })]
        }))
    };

Solution 12 - Javascript

This works fine as of now:

import { NavigationActions, StackActions } from 'react-navigation'

resetStack = () => {
        const navigateAction = NavigationActions.navigate({
            routeName: 'Home',

            params: {},

            action: NavigationActions.navigate({ routeName: 'Home' }),
        });

        props.navigation.dispatch(navigateAction);
    }

Found here in the docs: https://reactnavigation.org/docs/en/navigation-actions.html#reset

Solution 13 - Javascript

In your StackNavigator and DrawerNavigator you have used Home as a key, and i think it has to be unique and that's why its creating the problem. Can you please try replacing Home with Stack inside your DrawerNavigator.

Hope this will help :)

Solution 14 - Javascript

React Navigation 6.x

You can use popToTop() action to reset your stack. example:

import { StackActions } from '@react-navigation/native';

navigation.dispatch(StackActions.popToTop());

React-Navigation Docs: https://reactnavigation.org/docs/stack-actions/#poptotop

Solution 15 - Javascript

This fixed the issue for me (React Navigation 5.x)

import {NavigationActions} from 'react-navigation';

navigation.reset(
  [NavigationActions.navigate({routeName: 'Profile'})],
  0,
);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanielView Question on Stackoverflow
Solution 1 - JavascriptMahdi BashirpourView Answer on Stackoverflow
Solution 2 - JavascriptRobin DehuView Answer on Stackoverflow
Solution 3 - JavascriptSafeerView Answer on Stackoverflow
Solution 4 - Javascriptagm1984View Answer on Stackoverflow
Solution 5 - JavascriptGustavo GarciaView Answer on Stackoverflow
Solution 6 - JavascriptMahdi BashirpourView Answer on Stackoverflow
Solution 7 - JavascriptpeterorumView Answer on Stackoverflow
Solution 8 - JavascriptTim HysniuView Answer on Stackoverflow
Solution 9 - JavascriptNelson BasseyView Answer on Stackoverflow
Solution 10 - JavascriptKosalram Rama KrishnanView Answer on Stackoverflow
Solution 11 - Javascriptanshul gargView Answer on Stackoverflow
Solution 12 - JavascriptGvs AkhilView Answer on Stackoverflow
Solution 13 - JavascriptVijay SuryawanshiView Answer on Stackoverflow
Solution 14 - JavascriptAli RadmaneshView Answer on Stackoverflow
Solution 15 - JavascriptSaran RajView Answer on Stackoverflow