React native clear Stack Navigator stack - javascript

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)}

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'}],
});

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)

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..

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/

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.

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: "..." },
},
),
}),
);

//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)

Related

React-navigation reset function is not passing parameter

Someone now how to pass parameters effectively with navigation.reset() function?
I have tried to pass parameters to the react-navigation reset function but got always undefined so far
First try:
import {CommonActions} from '#react-navigation/native';
navigation.dispatch(
CommonActions.reset({
index: 0,
routes: [
{
name: 'ConnectionStack',
params: {zob: 'zob'},
},
],
}),
);
Second try:
const MyComponent = ({navigation}) => {
navigation.reset({
index: 0,
routes: [{name: 'ConnectionStack', params: {zob: 'zob'}}],
});
};
params are always undefined but my navigation is reset like I want.

How to go to initialRoute with react-navigation when exiting a child stack navigator inside a drawer?

I build an app with react-native, expo and react-navigation. I have a main drawer navigator who has in it 2 other stack navigator. One stack navigator have 2 pages; Products and Product. When I click on one product in the Products page, it goes into the Product page. Ben if I click on another link in my drawer navigator, I would like that the Products page's stack navigator would return to it's initialRoute when leaving the stack navigator.
I tried to set the initialState for when I exit the stack navigator, it render the initialState when I click on the navigator link in my drawer navigator, but it doesn't work when I'm in the child page and exit the navigator. When I click again on Products in my drawer, instead of navigate to the Products page, it stayed on Product.
I can create statics links in my drawer navigator and use this.props.navigation.navigate to always go to this.props.navigation.navigate('Products'), but it will be the last thing I want. I would really love that my drawer navigator stays dynamic with what I pass to it.
I tried to this.props.navigation.navigate when the componentWillUnmountlifecycle goes on, but it didn't work.
How can I do this?
Thank you for your help!
Yes it is entirely possible to reset the stack with react-navigation, there is a specific action for this.
Here is an example when the drawer is in a tab navigation.
First we define our drawer in MenuDrawer.js, nothing special here:
import { createDrawerNavigator } from 'react-navigation';
import ProductStack from './ProductStack';
import OtherStack from './OtherStack';
const MenuDrawer = createDrawerNavigator({
Product: {
screen: ProductStack,
navigationOptions: {
drawerLabel: 'My products',
},
},
Other: {
screen: OtherStack,
navigationOptions: {
drawerLabel: 'Something else',
},
},
});
export default MenuDrawer;
Finally we define our tab navigation, and we use the tabBarOnPress navigation option to listen to any drawer opening and reset the stack if needed:
import { createBottomTabNavigator, StackActions, NavigationActions } from 'react-navigation';
import MenuDrawer from './MenuDrawer';
const BottomTabs = createBottomTabNavigator({
Menu: {
screen: MenuDrawer,
navigationOptions: {
title: 'Menu',
tabBarOnPress: ({ navigation }) => {
const notResetRoute = navigation.state.routes.find(x => x.index > 0); // Check for stack not positioned at the first screen
if (notResetRoute) {
const resetAction = StackActions.reset({ // We reset the stack (cf. documentation)
index: 0,
actions: [
NavigationActions.navigate({ routeName: notResetRoute.routes[0].routeName }),
],
});
navigation.dispatch(resetAction);
}
navigation.openDrawer(); // Finally we open the drawer
},
},
},
});
export default BottomTabs;
Here the drawer is opened when the user clicks on the corresponding tab. Obviously the same could be made if the drawer is opened differently, for instance through a click on a button in a given screen. The important thing is to reset the stacks at the same time.
import { NavigationActions } from 'react-navigation'
this.props.navigation.dispatch(NavigationActions.reset({
index: 0,
key: null,
actions: [NavigationActions.navigate({ routeName: 'ParentStackScreen' })]
}))

React Navigation: Component is not being unmounted on pop or back button #5775

I am having an issue when I navigate from Home component that contains a list of companies and I press in a button to load the Company view, the data is being loaded but when I press back in Android is returning to Home and when I press in a different company button to load its details, is rendering the same view with the same previous data, that means, the component is not being updated/unmounted.
These are my routes
const drawerConfig = {
initialRouteName: 'Home',
contentComponent: SideMenu,
drawerWidth: width,
}
const MainDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: Home,
},
Company: {
screen: Company,
},
Gifts: {
screen: Gifts,
},
Contact: {
screen: Contact
}
},
drawerConfig,
);
const InitialStack = createStackNavigator(
{
Menu: {
screen: Menu,
path: 'menu/',
}
},
{
initialRouteName: 'Menu',
headerMode: 'none',
}
);
const SwitchNavigator = createSwitchNavigator(
{
Init: InitialStack,
App: MainDrawerNavigator,
},
{
initialRouteName: 'Init',
}
);
const AppContainer = createAppContainer(SwitchNavigator);
export default AppContainer;
I am navigating from Home to Company with this
goToCompany = company => event => {
this.props.navigation.navigate('Company', {
company,
});
}
And receiving the params in Company with this
componentWillMount() {
this.setState({ companyData: this.props.navigation.getParam('company', {}) });
}
So I am expecting the Company component will unmount on pop or allow me to change the state of the Company component when I send the details from Home.
I am using react-navigation 3.5.1 and react-native 0.59.3
React native navigation does not work as web. Read here for more details. https://reactnavigation.org/docs/en/navigation-lifecycle.html
When you navigat to other screen it doesn't actually get unmounted. Read documentation for details.
Use willFocus instead.
you can try using componentDidUpdate check in docs
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
You need to use the push method of navigation object. The push replace the current route with a new and the navigate search a route and if not exist create new one.

open react navigation app in a specific screen everytime

On the following example app:
https://github.com/callstack/react-native-paper/tree/master/example
if you do the following:
open the app
go to some specific screen
close the app
open the app
then, the app will be opened on the same screen it was just before closing it.
What I want to do is open the application in some specific screen everytime independently of the last visited screen.
On this link: https://reactnavigation.org/docs/en/stack-actions.html
I found the following code which could be useful:
import { StackActions, NavigationActions } from 'react-navigation';
const resetAction = StackActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'Profile' }),
NavigationActions.navigate({ routeName: 'Settings' }),
],
});
this.props.navigation.dispatch(resetAction);
but in case that it does the trick, my question is:
Where and how do I have to use that code?
Thanks!
const ScreenStack = createStackNavigator({
Screen1,
Screen2,
Screen3
},
{ initialRouteName: 'Screen1' })
You can define, initialRouteName for your first route..
But if you want to reset the router, create a NavigationService.
detail: https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

How to navigate from a child Stack Navigator back to parent while resetting navigation stack at the same time, in React Native

I've read countless react-navigation docs, and I know there is way to do this, but it's definitely what I would call non-trivial and definitely non-intuitive.
I have a root navigation stack:
export const NavigationStack = StackNavigator({
Splash: {
screen: Splash
},
Signup: {
screen: Signup
},
Login: {
screen: SignIn
},
ForgottenPassword: {
screen: ForgottenPassword
},
Discover: {
screen: Discover
},
ProfileShow: {
screen: ProfileShow
}
}, {
headerMode: 'none'
})
The ForgottenPassword screen is a child Stack Navigator:
import { StackNavigator } from 'react-navigation'
import PasswordResetProcess from './index'
const ForgottenPassword = StackNavigator({
ResetPassword: {
screen: PasswordResetProcess
}
}, {
headerMode: 'none'
})
export default ForgottenPassword
On that index.js Container Component, there is a sub-component that I pass navigation to, like this:
switch (lastCompletedStep) {
case NEW_RESET_REQUEST:
return <InputTel navigation={navigation} />
case INPUT_TEL:
return <ResetPassword navigation={navigation} />
That ResetPassword component is the one in question. It triggers an action creator and passes this.props.navigation into the action creator:
await props.handleResetSubmit(token, props.navigation)
From inside this action creator, props.navigation is available as navigation. I can do this fine:
navigation.navigate('Discover') // see how this is from the root Navigation Stack
I cannot, however, do this:
navigation.dispatch({
type: 'Navigation/RESET',
index: 0,
actions: [{ type: 'Navigate', routeName: 'Discover' }]
})
It throws this error:
[edit] I just tried this and it also generated the same error:
navigation.dispatch(NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Discover' })]
}))
How do I reset the stack while navigating to Discover from here?
I feel like the answer is to navigate to discover and reset the stack at the same time as some kind of child operation, but I don't know where to begin putting that together. The react-navigation documentation is horrendous for illustrating child to parent operations.
Here is my best guess at what it approximately has to look like:
navigation.dispatch({
type: 'Navigation/NAVIGATE',
routeName: 'Discover',
actions: [{ type: 'Reset', index: 0, key: null }]
})
I just solved it with this code:
navigation.dispatch(NavigationActions.reset({
index: 0,
key: null,
actions: [NavigationActions.navigate({ routeName: 'Discover' })]
}))
The secret was to add key: null, which I have seen people doing before. It is a very important element for times when you are resetting.
Here is the documentation I found that illustrates it:
https://github.com/react-community/react-navigation/issues/1127
I think this works because NavigationActions has knowledge of the root navigation stack, so it works for the same reason navigation.navigate('Discover') worked (in the context of my code in this question).
in version >2 of react navigation, NavigationActions.reset() doesnt work.
You should use StackActions.reset() instead:
import { NavigationActions, StackActions } from 'react-navigation';
const resetStackAction = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Discover' })],
});
this.props.navigation.dispatch(resetStackAction);

Categories

Resources