Comments (35)
Ok So I have a solution:
You need to add an index of 0 to your reset action:
dispatch({type: 'Reset', index: 0, actions: [{ type: 'Navigate', routeName:'Home'}]})
Haven't yet figured out how to run this only at the end of a transition - think you may need to use the Transitioner component
from react-navigation.
@JustinNothling, I would probably want to prevent the gesture. But I don't think there is a way to do that currently.
It might make sense to add a gesturesEnabled
screen navigation option, so a screen can toggle gestures based on the route.
from react-navigation.
That worked! Thanks! 😜
from react-navigation.
@ericvicenti we're in agreement about the reset
helper.
How would you go about structuring a simple login/logout using react-navigation? At the moment pushing a home route onto login allows users to goBack
to login using gestures (which isn't ideal). Would you reset the stack or would you prevent the gesture?
from react-navigation.
@JustinNothling I have, but I had to tweak a bit the code...
@satya164 I'm on master and by reading the docs it seems that for dispatching a reset action I need all I have to do is the following:
const actionToDispatch = NavigationActions.reset({
actions: NavigationActions.navigate({ routeName })
})
this.props.navigation.dispatch(actionToDispatch)
Which doesn't work.
The following does though:
const actionToDispatch = NavigationActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName })] // Array!
})
this.props.navigation.dispatch(actionToDispatch)
Is this the correct way to reset the stack? Am I just misunderstanding the docs? Let me know, I'd like to PR with a "clear way" for resetting the stack.
from react-navigation.
@JustinNothling, good point, we don't expose Transitioner's onTransitionEnd
through CardStack or StackNavigator
. That hasn't come up yet! Want to submit a PR?
I'm on the fence about adding a reset
helper because it doesn't always make sense for a child component to be aware of the application around it. Pretty soon people will want to add popAndReplace
and pushTwiceAndJumpBack
or whatever :-) . The replace option won't always be practical, because the screen can't see the whole navigation state (nor should it! you don't want every screen to re-render when one of their state changes). Instead, to support complicated navigation behaviors, you may want to override behavior on the router: https://reactnavigation.org/docs/routers/#Custom-Navigation-Actions
from react-navigation.
I fixed my issue by restraining myself to only one level of depth in my navigation, without deep linking.
const MainScreenNavigator = TabNavigator({
Recent: { screen: RecentScreen },
Logout: { screen: LogoutScreen },
})
const AppNavigator = StackNavigator({
FacebookAuthentication: { screen: FacebookAuthScreen },
EmailAuthentication: { screen: EmailAuthScreen },
Home: { screen: MainScreenNavigator },
})
from react-navigation.
@Paul-Todd hi Paul, this is the code I use in my Home screen:
class HomeScreen extends Component {
redirectKey = null
render = () => {
const { redirectRoute, redirectKey, redirectParams } = this.params
if (redirectRoute && redirectKey != this.redirectKey) {
this.redirectKey = redirectKey
setTimeout(() => {
this.props.navigation.navigate(redirectRoute, redirectParams)
}, 0)
}
return (
<HomeView
navigation={this.props.navigation}
/>
)
}
}
Putting the redirect logic in componentDidMount doesn't work, as componentDidMount is only called once on the home screen (not sure when it is unmounted).
From another page I then reset to the home screen as follows:
import { NavigationActions } from 'react-navigation'
import shortid from 'shortid'
const resetRoute = (navigation, params) => {
navigation.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'Home',
params: params,
}),
],
}),
)
}
class SomeOtherScreen extends Component {
handlePress = () => {
resetRoute(this.props.navigation, {
redirectRoute: 'ScreenToRedirectTo',
redirectKey: shortid(),
redirectParams: {
... params for ScreenToRedirectTo ...
},
})
}
...
}
NOTE: the shortid()
is necessary in order to only perform the redirect once (e.g. if the user pressed "back" to go back to the home screen we no longer wish to perform a redirect).
Disclaimer: This code is pretty terrible, I don't recommend using it if you can avoid it :)
from react-navigation.
Awesome, that works! Maybe it would be useful to have a 'reset' function on the 'navigation' object?
from react-navigation.
Hey has anyone got the new code on for reset in the docs to work?
https://reactnavigation.org/docs/navigators/navigation-prop
import { NavigationActions } from 'react-navigation'
NavigationActions.reset({
actions: NavigationActions.navigate({ routeName: 'Profile'}),
})
I'm getting an error saying reset is undefined.
from react-navigation.
Ok so the issue is not necessarily with the reducers so much as how to use the reset action. What you need to do is make sure you set the correct index. This works for me:
this.props.navigation.dispatch(
NavigationActions.reset({
index: 1,
actions: [
NavigationActions.navigate({
routeName: 'Home',
}),
NavigationActions.navigate({
routeName: 'Bar',
params: {
...,
},
}),
],
}),
)
Setting the 'index' as part of the 'navigate' doesn't seem to work.
from react-navigation.
Hey Mark, I got the same problem on my end so I'll let you know if I come up with a solution.
from react-navigation.
You might fine this useful. It is a variation of the tutorial where I have a login screen and then a logout function under the Options right element of the RecentChatsScreen which will get you back to the original login screen.
import React from 'react';
import {
AppRegistry,
Text,
View,
Button
} from 'react-native';
import { StackNavigator, TabNavigator } from 'react-navigation';
class SigninScreen extends React.Component {
static navigationOptions = {
title: 'Sign In',
};
render() {
const { navigate } = this.props.navigation;
return (
Sign In
<Button
onPress={() => navigate('Home')}
title="Sign In"
/>
);
}
}
class OptionsScreen extends React.Component {
static navigationOptions = {
title: 'Options',
};
render() {
const { navigate } = this.props.navigation;
const { dispatch } = this.props.navigation;
return (
Options!
<Button
onPress={() => {dispatch({type:'Reset', actions: [{ type: 'Navigate', routeName: 'Signin'}], index: 0 })}}
title="Logout"
/>
);
}
}
class RecentChatsScreen extends React.Component {
static navigationOptions = {
// Nav options can be defined as a function of the navigation prop:
header: (navigation) => ({
title: 'Recent Chats',
right: <Button title='Options' onPress={() => navigation.navigate('Options')} />
}),
};
render() {
return (
List of recent chats
<Button
onPress={() => this.props.navigation.navigate('Chat', { user: 'Lucy' })}
title="Chat with Lucy"
/>
)
}
}
class AllContactsScreen extends React.Component {
render() {
return (
List of recent chats
<Button
onPress={() => this.props.navigation.navigate('Chat', { user: 'Jane' })}
title="Chat with Jane"
/>
)
}
}
const MainScreenNavigator = TabNavigator({
Recent: { screen: RecentChatsScreen },
All: { screen: AllContactsScreen },
});
MainScreenNavigator.navigationOptions = {
title: 'My Chats',
};
class ChatScreen extends React.Component {
static navigationOptions = {
// Nav options can be defined as a function of the navigation prop:
title: ({ state }) => Chat with ${state.params.user}
,
};
render() {
// The screen's current route is passed in to props.navigation.state
:
const { params } = this.props.navigation.state;
return (
Chat with {params.user}
);
}
}
const TheApp = StackNavigator({
Signin: { screen: SigninScreen},
Home: { screen: MainScreenNavigator },
Chat: { screen: ChatScreen },
Options: { screen: OptionsScreen },
});
AppRegistry.registerComponent('exp', () => TheApp);
from react-navigation.
I have tried to implement Login/Logout using Reset action. However, with NestedNavigators I get the following error:
There is no route defined for key Home. Must be one of: 'FacebookAuthentication','EmailAuthentication'
I run the redux implemantation, like in the docs, so in a middleware, I run:
// middleware
if (prevState.isAuthenticated !== nextState.isAuthenticated) {
const nextScreen = nextState.isAuthenticated
? 'Home'
: 'Authenticate'
dispatch({
type: 'Reset',
index: 0,
actions: [{
type: 'Navigate',
routeName: nextScreen,
}],
})
}
Here is my reduced Navigator config:
// Navigator settings
const AuthenticateNavigator = StackNavigator({
FacebookAuthentication: { screen: FacebookAuthScreen },
EmailAuthentication: { screen: EmailAuthScreen },
})
const MainScreenNavigator = TabNavigator({
Recent: { screen: RecentScreen },
Logout: { screen: LogoutScreen },
})
const AppNavigator = StackNavigator({
Authenticate: { screen: AuthenticateNavigator },
Home: { screen: MainScreenNavigator },
})
from react-navigation.
Actually, the reset action doesn't seem to work properly. If I reset to 'Home' it works, but if I add additional actions to the reset it doesn't navigate to the right screen and seems to "freeze" (no button presses get registered). This is the code:
dispatch({
type: 'Reset',
index: 0,
actions: [
{
type: 'Navigate',
routeName: 'Home',
},
{
type: 'Navigate',
routeName: 'Items',
},
],
})
This is the state:
{ action:
{ type: 'Reset',
index: 0,
actions:
[ { type: 'Navigate', routeName: 'Home' },
{ type: 'Navigate', routeName: 'Items' } ] },
newState:
{ index: 0,
routes:
[ { routeName: 'Home', key: 'Init0' },
{ routeName: 'Items', key: 'Init1' } ] },
lastState:
{ index: 3,
routes:
[ { routeName: 'Home', key: 'Init' },
{ type: 'Navigate',
routeName: 'Items',
params: undefined,
action: undefined,
key: 'id-1485774310007-0' },
{ type: 'Navigate',
routeName: 'Menu',
params: undefined,
action: undefined,
key: 'id-1485774310007-1' },
{ type: 'Navigate',
routeName: 'Checkout',
params: undefined,
action: undefined,
key: 'id-1485774310007-2' } ] } }
from react-navigation.
The workaround that works for me is to set up deep linking and use Linking.openURL(...). However, this will only work well if you are happy with a navigation stack of 1 level deep (where the back arrow points back to home).
from react-navigation.
Maybe I'm misunderstanding, but shouldn't it be possible to simply dispatch a goBack, if you want a simple pop?
{type: 'goBack', ...}
Or do we need to manually dispatch reset actions in this case?
from react-navigation.
@lslima91 a goBack()
only works if you navigated into the second screen. In the case where eg: user was already logged in and they press logout -> this should call reset and not goBack
because we never went from logged out screen to home screen.
-> At least i think this is the functionality of goBack()
please correct if I'm wrong
ps: I am also running into this issue, it looks like a second action cannot be sent to the child router.
from react-navigation.
@elliottjro The thing is, I'm not able to dispatch a type: goBack action. I have to manually dispatch a reset with the correct routename.
from react-navigation.
@lslima91 the goBack()
method isn't an available type to be sent via dispatch()
. You have to call goBack()
directly on the navigation
prop. reference
Example:
<Button onPress={ () => this.props.navigation.goBack() } />
from react-navigation.
nvm, I have to dispatch {type:'Back'}, this new PR makes things much better imo #120
from react-navigation.
@JustinNothling are using the version from master?
from react-navigation.
the second one is correct. seems there's an error in the doc. willing to send a PR?
from react-navigation.
@mmazzarolo,
this.props.navigation.dispatch
doesn't seem to be doing anything on my app. To give some context, I didn't integrate react-navigation with a redux store.
from react-navigation.
Copy-paste from #156
@rohit-ravikoti the snippet you pasted is not using redux, it is just plain react-navigation
(which uses a pattern similar to the one used in redux).
I'm using it right now and it is working correctly.
Make sure you're using the master
branch though!
- Remove your current version of react-navigation:
npm uninstall react-navigation
- Add the master branch one:
npm install --save https://github.com/react-community/react-navigation.git
- Restart the packager
npm run start -- --reset-cache
- Fire up your emulator
Let me know if it works :)
from react-navigation.
Hey all, it looks like this issue is fixed but original issue was using the reset action along with a nested navigation action.
@markflorisson can you confirm this is the case else close current issue.
from react-navigation.
Hi @elliottjro, yeah the refactor looks great but nested navigation actions still don't seem to work:
this.props.navigation.navigate(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'Home',
}),
NavigationActions.navigate({
routeName: 'Items',
params: {
...
},
}),
],
})
)
from react-navigation.
Or do we have to nest the second 'navigate' action inside the first one, like so?
this.props.navigation.navigate(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'Home',
actions: [
NavigationActions.navigate({
routeName: 'Items',
params: {
...
},
}),
]
}),
],
})
)
from react-navigation.
BTW the most reliable way to work around is it to navigate to the 'Home' screen with a param, and then to do a 'navigate' from the Home screen to whereever you need to redirect. But it's a hassle and it involves an unnecessary rendering of the home screen.
from react-navigation.
@markflorisson, it can be hard to see what is going wrong exactly. Can you write a test for StackRouter.getStateForAction
, and verify that the reset action works correctly? The failing test will make the bug super clear.
from react-navigation.
@markflorisson - do you have an example of navigation with the param? I am stuck in the way at the moment
from react-navigation.
@ericvicenti Will give it a go, thanks!
from react-navigation.
(BTW: What is the reason for 'index'? Can the reducer not just take 'actions.length'?)
from react-navigation.
Theoretically, I think index should be optional and would default to actions.length
, but we don't have that feature right now. PR would be accepted for it.
Closing this out because it seems like everything is working. And I'll continue to think about how the API could be improved.
from react-navigation.
@CoteViande This solved ALL my navigation problems!
from react-navigation.
Related Issues (20)
- Drawer headerRight button also opens in the headerLeft. HOT 2
- React native bottom tab bar pushing itself up when opening keyboard HOT 3
- ReactNavigation doesn't build on ReactNative 0.73.5 on iOS (on Android everything is ok) HOT 1
- React native tabview stuck on iOS while switching tabs HOT 3
- Screen presentation type "modal" flickers when opening datepicker on iPhone SE (2022)
- Header focus issue on AndroidTV HOT 1
- 'createDrawerNavigator' is crashing the app
- Height of header with active search input seems to be ignored during back navigation transition on iOS
- 7.0.0-alpha `static` router conditional not working on iOS HOT 6
- Issue unit testing a navigation container (createInteractionHandle is not a function) HOT 3
- Elements with `position: absolute` disappear during screen transition HOT 3
- Crash due to useNativeDriver true for tab animations with android 12 devices HOT 2
- Cannot read property 'name' of undefined in "MaterialTopTabView" HOT 4
- Dropdown and popover components opening at incorrect position in iOS when using default header in React Navigation 6 stack HOT 2
- getState typescript error after version 6.1.10 HOT 1
- Header height not getting calculated in pageY value for components in new architecture HOT 3
- Incorrect pageY value when only using default header of react navigation stack in new architecture HOT 3
- v7 Navigating back randomly causes NAVIGATE action to be dispatched instead of GO_BACK HOT 2
- Possible EventEmitter memory leak detected HOT 1
- Pressable interaction issue with StackNavigator on iPhone Xs + new architecture HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-navigation.