-
-
Notifications
You must be signed in to change notification settings - Fork 5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reset to nested route, "There is no route defined for..." #1127
Comments
Yeah this needs to be fixed |
A quick workaround (not heavily tested): set the key property to null on your action.
|
@hasty Thanks, that works. I can remove the |
@hasty Thank you) This works for me. But the "index" property is not need to add for this. (May be in my case only) |
cc: @ericvicenti |
I just ran in to this issue too, would be nice to see more fine grained targeting for actions when using nested navigators. |
thanks @hasty setting key to null worked for me. I had the same issue with the Back action with nested navs. |
Unluckily setting the Basically, my nesting goes like this:
Given that I pass as but, if I write it this way:
It returns |
Two things:
|
They @hasty, thanks for your feedback:
|
Tried @hasty approach, unfortunately, without success.
Which gives me the following error: There is no route defined for key Login. Must be one of: Credentials, Access (and I'm at MainNavigator, so this makes no sense to me) So I literally changed Login to Credentials as literally stated on the Error, and got this new Warning: setState(...) can only update a mounted or mounting.... Which is just a warning BUT, stills my navigation is not reset, I still can go back. Of course I also tried to stack up all actions nested NavigationActions as stated in docs
|
@betocantu93 What worked for me is almost exactly what you have, except I wrapped the second dispatch in a I don't know enough about the internals to really explain why that worked, but I guess the first navigate action is asynchronous. |
I think this is a feature that is requested: #1206 |
@jamesisaac Thanks alot for your answer, I'm working towards implementing/debugging your approach, but when reset action proceeds (after timeout) it seems to completely ignore the whole purpose of reset since the stack stills shows on the middleware the navigation history stack on New State; nothing happens, Login screen stills render the back button (And in other scenario I maybe just would hide it or something) but here it's not possible because of android's back button. |
Ok what I did, and I don't like it. I have this: Splash: {screen: Splash},
I navigated from a HomeStack screen (AddVehicle) to Splash, the only thing Splash do is check credentials and a normal parent reset (single navigation action). Somehow, it worked. BUT right now I can see the back navigation animation going through all of the previous screens, which I don't like. |
Yeah, the |
Similar situation here. My ideal navigation structure would be Stack Navigator wrapping single Stack Navigator (Login) and a Drawer Navigator with multiple child Stack Navigators. Right now, everything is wrapped in a Drawer Navigator so I can navigate as best as I can without using reset, the downside is that a user can open the drawer with a swipe action on the Login screen. Even with my current implementation, reset won't work as described in this issue. Here is where I'm trying to trigger it from.
My dispatch action
|
@RobertSheaO I have a similar set up, except I pull the LogIn screen one navigator back:
With this setup, I can't swipe to open the drawer from the Login screen. |
Yes @matthamil, that is my ideal setup, but then I run into even more issues with reset not working. Do you have an example of reset working inside your app, that takes them out of your DrawerNavigator and back to the Login screen? |
Sure: import { NavigationActions } from 'react-navigation';
// inside my class component
logoutUser() {
const { logoutUser } = this.props;
logoutUser(); // clears cache of user info
navigation.navigate('LogIn');
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'LogIn' })
]
});
setTimeout(this.props.navigation.dispatch.bind(null, resetAction), 500);
} This is a bit of a hack given that you can't dispatch multiple navigation actions at once. What I'm doing is navigating to the log in screen, then half a second later resetting the navigation stack. This prevents the user from pressing the Android "back" button to return to the previous screen. |
Don't reset and will work! something like NavigationActions.navigate({ routeName: 'LogIn' }) |
@ghitatomy In this case, Also, depending on your nested navigation structure, doing navigate will prompt you with a warning that "There is no route for X". |
You can reset it on logout. |
Hi all, Did anyone get this working? |
1.0.0-beta.10 still not working |
This issue has forced me to add a bunch of navigation outside of react-navigation, to the point that I question why I'm still using it. I love where this project is heading it just seems to be missing a nice way of managing global navigation from within nested states. Anyone find easier ways? none of the solutions in this thread, or elsewhere seem to work for me. |
Since reset doesn't seem to understand how to traverse state relationships between nested navigators, the current hack i've settled on is to define reducers for each navigator that handle the state transitions independently. Reset still doesn't work in that context, but you can |
insert your TabNavigator
Hope it will help you. |
I have almost the same issue as a few other people with a nav tree like
In order to jump from
I guess it is almost the same solution as the suggested setTimeout, except that you don't need it and just wait for navigation to finish by using async/await. Is this feasible or am I just lucky that it is working? |
I am replacing my former comments with the following. First of all thank you all who are working to make this better, unpaid and often without credit from others. As I get better at this I will attempt to also help out. Thank you for the following comments which really helped. I will look them over for guidance. I went back to all my notes and found the following:
Inserting the call to that into my DrawerNavigator:
Allowed me to make a call to my Drawer and thus let me reset my route... I made a pretty large app which works, but without the best practices and knowledge of where exactly everything goes, it was unwieldy. I am back in the game to make my app work and work correctly, I am using ignite as a nice starting place to get my redux, reactotron, saga, and other parts in line. My previous comments on react-native-router-flux was just that it was working, and for the last year I was worried about the fact that react-native has told the community that react-navigation is the future. Anyway thanks for all your help and advice. |
@cyphire Sorry React Navigation isn't working for you. To clarify, React Navigation came out in late January of this year (2017) and this issue was opened in April. It's also fair to point out that React Navigation is still in Beta. With that being said, I 100% feel your frustration. I've been using React Navigation since it came out and it took while to get it right. A lot of issues I've had required me to go back to the drawing board and really think about what and why I was trying to approach it in the way I was. Here's a few snippets of my app, which is in production on the App Store and Google Play. The only "hacky" thing is specifying Setup StuffApp.js (imported by index.ios.js/index.android.js)export default class App extends Component {
render () {
return (
<Provider store={store}>
<RootContainer />
</Provider>
)
}
} RootContainer.jsclass RootContainer extends Component {
render () {
return (
<View style={styles.applicationView}>
<ReduxNavigation />
</View>
)
}
}
export default connect(null, mapDispatchToProps)(RootContainer) ReduxNavigation.jsfunction ReduxNavigation (props) {
const { dispatch, nav } = props
const navigation = ReactNavigation.addNavigationHelpers({
dispatch,
state: nav
})
return <AppNavigation navigation={navigation} />
}
const mapStateToProps = state => ({ nav: state.nav })
export default connect(mapStateToProps)(ReduxNavigation) React Navigation SetupAppNavigation.jsconst PrimaryNav = StackNavigator({
LoginScreen: { screen: LoginScreen },
AppScreen: { screen: TabNavigation }
}, {
headerMode: 'none',
initialRouteName: 'LoginScreen',
navigationOptions: {
headerStyle: styles.header
}
})
export default PrimaryNav LoginScreen.jsclass LoginScreen extends Component {
render () {
return (
<Button onPress={() => this.props.onLogin()}>
<Text>Login</Text>
</Button>
}
}
const mapStateToProps = (state) => {}
const mapDispatchToProps = (dispatch) => {
return {
onLogin: () => {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: 'AppScreen'})
],
key: null
})
dispatch(resetAction)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen) TabNavigation.jsexport default TabNavigator({
Home: {
screen: HomeNavigation,
navigationOptions: {
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor }) => <Icon name='home' color={tintColor} size={24} />
}
},
Setting: {
screen: SettingNavigation,
navigationOptions: {
tabBarLabel: 'Settings',
tabBarIcon: ({ tintColor }) => <Icon name='settings' color={tintColor} size={24} />
}
}
}, {
initialRouteName: 'Home',
order: ['Home', 'Setting'],
tabBarComponent: TabBarBottom,
tabBarPosition: 'bottom',
swipeEnabled: false,
animationEnabled: false,
lazy: true
}) SettingNavigation.jsconst routes = {
Index: { screen: SettingScreen },
Support: { screen: SupportScreen },
WebContent: { screen: WebContentScreen }
}
const config = {
headerMode: 'float'
}
export default StackNavigator(routes, config) SettingScreen.jsclass LoginScreen extends Component {
render () {
return (
<Button onPress={() => this.props.onLogout()}>
<Text>Logout</Text>
</Button>
}
}
const mapStateToProps = (state) => {}
const mapDispatchToProps = (dispatch) => {
return {
onLogout: () => {
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: 'LoginScreen'})
],
key: null
})
dispatch(resetAction)
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen) |
BTW, If you want an app that has both React Navigation, Redux, and Sagas baked in, check out Ignite. Their setup takes away a lot of headaches of setting up an app from scratch. Personally, I trigger all my import { combineReducers } from 'redux'
import { resettableReducer } from 'reduxsauce'
const resettable = resettableReducer('GLOBAL/LOGOUT')
const rootReducer = combineReducers({
nav: resettable(require('./NavigationRedux').reducer),
global: resettable(require('./GlobalRedux').reducer),
login: resettable(require('./LoginRedux').reducer),
home: resettable(require('./HomeRedux').reducer),
setting: resettable(require('./SettingRedux').reducer),
persistent: require('./PersistentRedux').reducer
}) P.S. React Native can take awhile to get the hang of, but once you do, it's well worth it. I've been using it a little over a year now and am very happy I did. I now have three full fledged apps written with it, and they all use React Navigation. Two of these apps are published at the time of this writing. |
Thanks @RobertSheaO for your comments, made my day. |
I think we should try and migrate the discussion about the lib itself into the other thread @kelset mentioned (#2031). I appreciate both sides but at the end of the day this issue is for the bug affecting people. I imagine those ~40 devs watching this issue are mostly looking for notifications about when it has been fixed. If @kelset, @RobertSheaO, or other folks more familiar with library could triage and point to where in code/dependencies/timeline this can be fixed, maybe one of us can step in to contribute towards a fix. My superficial understanding was we need to add something like in #1025 but probably some edgecase or section of codebase was missed in that PR. React native itself is under very active development so bugs are bound to arise in ecosytem. Discussion that might help someone or myself to patch the issue would be appreciated. I mean this sincerely -- not trying to be snarky. This library and its contributors are doing great work trying to give us a decent, reliable navigation library. 🙏🏻 |
Thanks @RobertSheaO and thank you @kelset ! I have a huge unwieldy application because there is no real guide to putting a big (whole) application together. I made the mistake of both trying to learn and use redux at the SAME TIME I changed the navigation from react-native-router-flux (Thanks @aksonov !) which worked, but I was afraid to stay with it because of the articles touting react-navigation.org as the future of react-native navigation. I finally understand Redux enough to implement it! The ignite (again thank you!) way works great, the Reactotron configs actually work and can let me see my state, and I'm on my way to build my app the right way. |
@RobertSheaO, This will work for the parent route
But if I try navigate to any child route from a diferente parent, it will crash
Like here
If I'm on /LoginNav and call /Register will work If I'm on /LoginNav and call /Dashboard will fail |
@rochapablo Try adding const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: 'Dashboard'})
],
key: null
})
this.props.navigation.dispatch(resetAction) Here's a breakdown of my navigation stack:
Here is a snippet of my reducer setup, where I listen for LOGOUT and reset import { combineReducers } from 'redux'
import { resettableReducer } from 'reduxsauce'
const resettable = resettableReducer('LOGOUT')
const rootReducer = combineReducers({
nav: resettable(require('./NavigationRedux').reducer),
login: resettable(require('./LoginRedux').reducer),
global: resettable(require('./GlobalRedux').reducer),
persistent: require('./PersistentRedux').reducer
}) |
Any news on this ? i have TabNav
On profile i try to dispatch on logout click this.props.navigation.dispatch(
NavigationActions.reset({
index: 0,
key: null,
actions: [NavigationActions.navigate({ routeName: 'Home' })]
})
) // Force to be on the Home screen But this is matching the router of Explore... I don't know why |
Same issue like "PR" @aroth and don't have any solution in above discussion, if anyone get the solution so please let us know. Its a very critical problem with react native. How we can move ahead with this technology. Its not good for React-Native Community. I am totally disappointed :( ......... 👎 |
Any update please? |
I test out new version recently and tried all old version from 1.0.1 until 1.1.2. please use react-navigation@1.0.0-beta.19 for dispatch feature |
If you are like me and you landed on this thread because reseting the stack caused problems with the order of the stack, here's a fix: So for example instead of building the stack inside of the
You need to instead reset the stack with one navigation action and dispatch any subsequent navigation actions afterwards:
For some reason the second The action below, for example, would not fire off inside of reset 😞
|
@Ariflo thanks. seems like it really need to separate to different dispatch. still, this is quite annoying. Cant we do like this?
then this can support in nested stack navigator and tab navigator. for now we need to do like below to handle nested navigator
|
I had an issue using reset with a nested screen, however you could navigate to the root route then from that route you could make a sub action to navigate to your nested route. example:
reference : https://reactnavigation.org/docs/navigation-actions.html#navigate (action) |
@kareem-adel had tried your solution but not exactly what I want.
|
the OP's problem is resolved using
you can read more about SwitchNavigator here: https://reactnavigation.org/docs/switch-navigator.html if you have another issue that is similar to the one described by the OP but not solved by this, please create a new issue. thanks! |
PR #1025 has resolved issues when attempting to
navigate
between nested navigators (#983, #704). Thanks for the fix, @grabbou.Would it be possible for
reset
to behave the same way? Consider this navigation structure:On Sign Up or Login, I'd like to
reset
to Authorized.On Sign Out, I'd like to
reset
to Unauthorized.In master, if I attempt to
reset
I'm gettingThere is no route defined for key Authorized. Must be one of: Welcome, Login, SignUp
.If I
navigate
, it works.Strangely enough,
reset
does work properly if I wrap the components like so:cc: @henrikra
The text was updated successfully, but these errors were encountered: