-
-
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
[Solution] Reset to specific tab screen in a nested navigator #1715
Comments
interested , looking for someone to answer |
@pvsong do you mean put the state of tab 2nd screen into storage or redux? But how can I reset to this screen? |
+1 |
It would be fantastic if someone knew |
@pvsong Hey bro, I cannot figure out the solution, can you demonstrate some code for the navigate part? Thanks a lot. |
I've been pulling my hair out for months on how to get reset to work in this exact situation, some examples from those who made it work would be great. I'm trying to get this to work on a basic app, no redux or anything. |
Imagine you have the following set up: // OuterNavigator.js
import { StackNavigator } from 'react-navigation';
import { headerMode, navigationOptions } from '../config';
import SubNavigator from './SubNavigator';
import ParentView from '../../views/OuterView';
const OuterNavigator = StackNavigator(
{
Outer: { screen: OuterView },
Inner: { screen: SubNavigator },
},
{
headerMode,
navigationOptions,
initialRouteName: 'Outer',
}
);
export default OuterNavigator; // SubNavigator.js
import { StackNavigator } from 'react-navigation';
import { headerMode, navigationOptions } from '../../routes/config';
import InnerViewA from '../../views/InnerViewA';
import InnerViewB from '../../views/InnerViewB';
const SubNavigator = StackNavigator(
{
ViewA: { screen: InnerViewA },
ViewB: { screen: InnerViewB },
},
{
headerMode,
navigationOptions,
initialRouteName: 'ViewA',
}
);
export default SubNavigator; Let's say that you want to navigate to Simply using a To use // OuterView.js
export default class OuterView extends React.Component {
render() {
const navigation = this.props.navigation;
return (
<View
<Button onPress={() => navigation.navigate('Inner', { parentNavigation: navigation })}>
<Label>Go to Inner</Label>
</Button>
</View>
);
}
} // InnerViewB.js
export default class InnerViewB extends React.Component {
render() {
const parentNavigation = this.props.navigation.state.params.parentNavigation;
return (
<View
<Button onPress={() => parentNavigation.dispatch(
NavigationActions.reset({
key: null,
index: 0,
actions: [
NavigationActions.navigate({
routeName: 'Outer',
}),
],
})
)}>
<Label>Go to Inner</Label>
</Button>
</View>
);
}
} |
@lukem512 Hey bro, reset to outerView is working probably. But the current issue is how to reset to the subview of outerView. |
By a subview do you mean const OuterNavigator = StackNavigator(
{
OuterA: { screen: OuterView },
OuterB: { screen: AnotherOuterView },
Inner: { screen: SubNavigator },
},
{
headerMode,
navigationOptions,
initialRouteName: 'OuterA',
}
); |
@lukem512 Hey bro, the view structure is
Can it reset from innerViewA / innerViewB reset to OuterViewB. |
If you pass the |
After facing similar issue but from deep links, I started investigating and came up with a solution. I hope this helps :)
|
@fdnhkj i do not think this solution works for the reset() nav action. I tried it. The only reasonable work around I have without a code change to react-navigation is saving something to async storage or passing an event handler function that gets called to switch tabs. |
I found a temporary trick until they provide us the feature to dynamically change the initialRouteName of the TabNavigator.
So your default navigator is RouteBase that open by default Root (MainScreen). So now let's imagine you are in SomeOtherStack and want to reset to Tab2:
This make the trick. I hope there will be better solution coming soon... |
HI I have following structure Login After login, I want my user to navigate from Login screen to InnerHome. Below is my code... const MainTabNavigator = TabNavigator({
}); const MainStack = StackNavigator({
},{
}); Now if user is already logged in , I want user to directly redirect from Home screen to InnerHome I have done something like this... const redirectWelcome = NavigationActions.reset({ componentDidMount() {
} ..... but this is not working... (I have observed componentDidMount is calling infinite time of this screen only) Please help me in this. |
Any fix for this issue ? |
DISCLAMER: This is a very hacky way but it worked for me:
But it might lead to a better temporary solution. Hope it helps |
@JorgeCeja Thanks a ton, this hacky thing worked for me. :) |
@appwudo Thanks for bringing me back to sanity. I spent a couple hours trying to do this without having to have multiple screen |
@JorgeCeja thanks! Saved my the whole of my life |
@JorgeCeja navigation actions are synchronous, so you don't need promises, this should work the same way: navigation.dispatch(
NavigationActions.reset({
index: 0,
// TabNav is a TabNavigator nested in a StackNavigator
actions: [NavigationActions.navigate({ routeName: 'TabNav' })]
})
);
navigation.navigate('specificScreen')) |
I can confirm dispatching 2 actions synchronously work fine. export const navigateToRootTab = (navigation,tabName) => {
const actions = [
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: "Root",
}),
]
}),
NavigationActions.navigate({
routeName: tabName,
})
];
actions.forEach(navigation.dispatch);
}; Yet I would also have expected the reset navigation sub-action to work and being able to set the navigation in expected state with a single action. |
this seems popular, can someone submit a guide to the website explaining how to do it and the use cases? http://github.com/react-navigation/website |
@brentvatne I'd add this to documentation but it would be great to know first if this is the indented behavior. For me, the following not working looks like a bug: NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: "Root", // StackNav root, whose screen is a TabNav
action: NavigationActions.navigate({
routeName: tabName, // This does not work, the TabNab is always reset to its initialRouteName
})
}),
]
}); if this is confirmed to be a bug, I think we should work on resolution, instead of documenting a temporary workaround. So, can someone confirm it's a bug? |
Agreed. Unless nested actions are being done away with, I think this is a hack/workaround. |
It's definitely a hack/workaround, but not really that convoluted. Here's how I'm handling it (credit to @appwudo ) with success (aside from currently-mounted screens quickly animating as the
|
@wkoutre doesn't that create a copy of the whole stack, doubling your rendered elements? |
@JulianKingman No -- at least not to my knowledge, anyway. I've set
|
this is a pretty long issue but if I understand it correctly then this rfc should solve it when implemented: react-navigation/rfcs#25 |
@brentvatne I've read the RFC but not sure to understand how it is related. Will this work after the RFC is implemented? NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: "Root",
action: NavigationActions.navigate({
routeName: tabName,
})
}),
]
}); |
|
Thanks @brentvatne . So, if this is possible, what's the purpose of passing an extra navigate action like in my code above? In which case would you use this navigateAction sub-action? |
@slorber, @brentvatne I am using the following code: const HomeStack = StackNavigator(
{
Home: { screen: HomeScreen },
Category: { screen: CategoryScreen },
Details: { screen: DetailsScreen }
},
{
initialRouteName: "Home"
}
);
const FavouriteStack = StackNavigator({
Favourite: { screen: FavouriteScreen }
});
const SettingsStack = StackNavigator({
Settings: { screen: SettingsScreen }
});
export default TabNavigator(
{
HomeTab: { screen: HomeStack },
FavouriteTab: { screen: FavouriteStack },
SettingsTab: { screen: SettingsStack }
},
{
tabBarPosition: "bottom",
tabBarComponent: props => {
return (
<Footer>
<FooterTab>
<Button
vertical
active={props.navigationState.index === 0}
onPress={() => props.navigation.navigate("HomeTab")}
>
<Icon name="home" />
<Text>Home</Text>
</Button>
<Button
vertical
active={props.navigationState.index === 1}
onPress={() => props.navigation.navigate("FavouriteTab")}
>
<Icon name="star" />
<Text>Favourite</Text>
</Button>
<Button
vertical
active={props.navigationState.index === 2}
onPress={() => props.navigation.navigate("SettingsTab")}
>
<Icon name="settings" />
<Text>Settings</Text>
</Button>
</FooterTab>
</Footer>
);
},
}
); Where do I put the reset navigation stack code? |
It depends if you use stateful navigator or not (ie using Redux). You can dispatch a navigation action if you use Redux, or you can wrap your navigator in a class comp, get a ref on it, and call dispatch on the navigator component instance |
I am not using Redux. When someone presses the home tab, it will reset the stack. I am new to react and react native. Please guide me. |
class StackNavigationWrapper extends React.Component {
componentDidMount() {
this.stackNavigationRef.dispatch(NavigationActions.reset({...}))
}
render() {
return (
<MyStackNavigator ref={c => this.stackNavigationRef = c}/>
);
}
} |
Hey all,
Currently, I have using the both the Tab and stack navigator.
I have using the Tab as the main navigator, and few stack as the sub screen.
There are 4 tabs in main Navigator, the 1st tab is the initialised screen.
My current structure:
How can I reset to the 2nd tab in its child stack screen? The reset to main navigator alway direct to the initialised screen.
Also, I tried navigate to this specific tab screen, it works probably, but I can't rest the stack from this screen. If there are any method to drop all the previous stack also can solve my problem.
Solution
Stupid solution, but it working if you have same structure as mine. I have using AsyncStorage, thus it works without redux/flux.
Your Environment
The text was updated successfully, but these errors were encountered: