Paras Watts
Paras Watts

Reputation: 2665

React native clear Stack Navigator stack

I have few screens which I navigate through one by one. Screen1->screen2-screen3->screen4-Home

What I want is when I go to home then the previous history of navigation should be cleared and back pressing back button should not go to last navigated screen which is screen 4. Currently When I press back button on home screen it takes me back to the last route in the stack which is screen4. I have used below code. It is giving me error no route defined or key Home. Which I have already defined in Screens class. Any help would be appreciated.

const resetAction = NavigationActions.reset({
  index: 0,                       
  actions: [NavigationActions.navigate({ routeName: 'Home' })],
});

onPress={() =>  this.props.navigation.dispatch(resetAction)}

Upvotes: 34

Views: 65361

Answers (8)

atmaram
atmaram

Reputation: 500

If someone is still looking for an approach, here is what I have implemented and working fine.

From entry point be it index.js or app.js in tree of all different <Provider....> {..}</Provider> use the <NavigationContainer>...</NavigationContainer>

Inside this NavigationContainer, declare all Routes be it Stack/Tab/Drawer etc.. inside single Stack, say RootStack. And inside this RootStack declare the routes in different combination of possibilities. E.g. Public Menus vs Secure Menus.

Example Below - All the screens are the actual Components rendering the pages. However the boolean checks can be enhanced upto any level to get the respective screen stack loaded.

<RootStack.Navigator
  screenOptions={{
    headerShown: false
  }}
>
  <RootStack.Screen name="HOME_PAGE" component={HomeScreen} />
  {!isOnlineMode ? (
    <RootStack.Screen name="OFFLINE_MEMBERS_PAGE" component={OfflineMemberScreen} />
  ) : (
    <>
      {isLoggedIn ? (
        <>
          <RootStack.Screen name="SECURE_PAGE_1" component={SecureScreen1} />
          <RootStack.Screen name="USER_PROFILE_PAGE" component={UserProfileScreen} />
          <RootStack.Screen name="LOGOUT_PAGE" component={LogoutScreen} />
        </>
      ) : (
        <>
          <RootStack.Screen name="LOG_IN" component={AuthScreen} />
        </>
      )}
    </>
  )
  }</RootStack.Navigator>

Upvotes: 0

Hayden
Hayden

Reputation: 101

With typed routes and their parameters

type StateRoute<Route extends keyof MyNavigatorParamList> = {
  name: Route;
  params: MyNavigatorParamList[Route];
};

const toNavigationStateRoutes = <Route extends keyof MyNavigatorParamList>(
  ...routes: StateRoute<Route>[]
) => routes;

navigation.dispatch(
  CommonActions.reset({
    index: 1,
    routes: toNavigationStateRoutes(
      {
        name: 'Home',
        params: undefined,
      },
      {
        name: 'Some screen',
        params: { id: "..." },
      },
    ),
  }),
);

Upvotes: 1

Rajesh N
Rajesh N

Reputation: 6673

in V5, you can use

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

Using hooks

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

const navigation = useNavigation();

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

Upvotes: 61

Harikesh
Harikesh

Reputation: 341

//import

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

//reset current navigation stack and create new navigation stack

const loginScreenAction = StackActions.reset({
    index: 0,                       
    actions: [NavigationActions.navigate({ routeName: 'LoginScreen' })],
});

//open new component with new navigation stack

this.props.navigation.dispatch(loginScreenAction)

Upvotes: 0

Charitha Goonewardena
Charitha Goonewardena

Reputation: 4714

With @react-navigation 5.x you can use CommonActions to reset/clear the stack. I'll leave an example here.

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

const handleSigninNavigation = () => {
 navigation.dispatch(
  CommonActions.reset({
    index: 0,
    routes: [{ name: "your-new-route" }]
  }));
}

Also you can create your own stack while resetting it. Just pass the names of the routes to routes array and give an index to navigate first.

CommonActions.reset({
  index: 1,
  routes: [{ name: "home" }, { name: "signin" }]
}));

Above code will reset the current stack with given routes and will navigate to the signin since we set the index to 1.

Upvotes: 5

Nelson Bassey
Nelson Bassey

Reputation: 71

If you use react-navigation@<=4 you can use a Switch Navigator.

You create a Switch Navigator with createSwitchNavigator. Such navigators do not stack up your navigation. Add your auth screen/navigator in a Switch Navigator 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/4.x/auth-flow/

Upvotes: 5

Fazeel Qureshi
Fazeel Qureshi

Reputation: 864

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

you can use this, this works for me..

Upvotes: 7

bennygenel
bennygenel

Reputation: 24660

As it states in the react-navigation docs for reset action, index should be the current active route's index. The error might be related to that.

How to use the index parameter

The index param is used to specify the current active route. eg: given a basic stack navigation with two routes Profile and Settings. To reset the state to a point where the active screen was Settings but have it stacked on top of a Profile screen, you would do the following:

import { NavigationActions } from 'react-navigation'

const resetAction = NavigationActions.reset({
  index: 1,
  actions: [
    NavigationActions.navigate({ routeName: 'Profile'}),
    NavigationActions.navigate({ routeName: 'Settings'})
  ]
})
this.props.navigation.dispatch(resetAction)

Upvotes: 10

Related Questions