How not to unmount previously opened screen of Drawer Navigator - javascript

I am using react-native-navigation and trying to create a DrawerNavigator which does not unmount the previously opened screens just like how TabNavigator works. Because one of my screens contains a webview and I do not want it to reload everytime I change screens.
Here is some sample code in App.js..
const Drawer = DrawerNavigator(
{
Home: { screen: Home },
PageWithWebview: { screen: PageWithWebview},
Settings: { screen: Settings },
},
{
initialRouteName: "Home",
contentComponent: props => <SideBar user={global.user} />
}
);
const AppNavigator = StackNavigator(
{
Drawer: { screen: Drawer },
},
{
initialRouteName: "Drawer",
headerMode: "none"
}
);
export default () =>
<Root>
<AppNavigator/>
</Root>;
And in my Sidebar component I have buttons to navigate to a different route depending on what is selected .
onPress={() => this.props.navigation.navigate(selected, { userDetails: global.user })}

In the later versions of react native navigation they added the unmountInactiveScreens property for the DrawerNavigator
unmountInactiveScreens
Whether a screen should be unmounted when navigating away from it. Unmounting a screen resets any local state in the screen as well as state of nested navigators in the screen. Defaults to false.

Related

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 SwitchNavigator - navigate between several stacks

I had to refactor recently the navigation inside my React Native App using React Navigation.
Indeed, I have several navigators inside my app for different purposes: screens when not connected, screens when connected and some screens that should be available in both situations
(e.g. terms of use).
So my question is the following, if I have this pattern, how can I for example navigate from TermsOfUse to Register without going back to Welcome?
I can't use navigate.goBack() or navigation.navigate('Register') since those screens are not in the same StackNavigator, and duplicate the TermsOfUse in both navigators would be quite dirty.
// Screens
const NotConnectedScreens = {
Welcome: { screen: WelcomeScreen },
Register: { screen: RegisterScreen },
}
const ConnectedScreens = {
Homepage: { screen: HomepageScreen },
Tutorial: { screen: TutorialScreen },
}
const OthersScreens = {
TermsOfUse: { screen: TermsOfUseScreen },
}
// Stacks
const NotConnectedStack = createStackNavigator(NotConnectedScreens, {
initialRouteName: 'Welcome',
})
const ConnectedScreens = createStackNavigator(ConnectedScreens, {
initialRouteName: 'Homepage',
})
const OtherStack = createStackNavigator(OtherScreens, {
initialRouteName: 'TermsOfUse',
})
// App navigation
const AppContainer = createAppContainer(
createSwitchNavigator(
{
NotConnectedStack: NotConnectedStack,
ConnectedStack: ConnectedStack,
OthersStack: OthersStack,
},
{
initialRouteName: 'LandingStack',
defaultNavigationOptions: {
header: null,
headerMode: 'none',
},
}
)
)
export { AppContainer as default }
I can't use navigate.goBack() or navigation.navigate('Register') since
those screens are not in the same StackNavigator.
Not completely true, if your screen has a unique name, wherever you need to navigate to that page you can call the function this.props.navigation.navigate('SecondPage').
but sometimes going to an screen from another stack can't be done because it needs some data to be passed when navigating to. in this case MAKE SURE YOUR SCREEN HAS A DIFFERENT NAME
DevicesList: {screen: DevicesList },// this is wrong
DevicesListPage: {screen: DevicesList },// this is right
then you can navigate to that page like below from another stack:
this.props.navigation.navigate('DevicesListPage', {
//your data
});

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.

React Navigation: Reset entire navigation state to initial values

I'm working on a RN app, and when a user signs out of the app I reset all the Redux state to it's initial values and navigate to the Login screen. However, on signing back in, the navigation state has been carried over, which is causing problems. How can I reset the navigation state, so each sign in acts like a completely new app session?
My navigation looks like this:
const MainNavigator = createBottomTabNavigator(
{
login: { screen: Login },
main: {
screen: createBottomTabNavigator(
{
home: {
screen: createStackNavigator({
...
}),
},
map: {
screen: createStackNavigator({
...
}),
},
},
),
},
},
{
initialRouteName: 'login',
},
);
Many thanks!
from the api https://reactnavigation.org/docs/en/navigation-prop.html#dismiss
Call dismiss if you're in a nested (child) stack and want to dismiss the entire stack, returning to the parent stack.
So, use that
this.props.navigation.dismiss()

How to navigate to directly to the initial route when using TabNavigator?

I am using TabNavigator from react-navigation. It's working fine but I need to do a little trick.
When I navigate between StackNavigator routes, after changing tabs I need my route go directly in the initial route. So I need the route state to be reset.
const HomeStack = StackNavigator({
Main: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
});
const AboutStack = StackNavigator({
Main: { screen: AboutScreen },
});
TabNavigator(
{
Home: { screen: HomeStack },
About: { screen: AboutStack },
}
Let's say I am in the Main route from the Home tab and then I have navigated to Profile before switching to the About tab. When I go back to the Home tab I want my app directly to navigate to the Main route and clear history. Just like a reset.
Any suggestion ?
You maybe could use the willFocus listener in the Profile route of your HomeStack.
Listener:
class Profile extends Component {
componentDidMount() {
this.didFocusListener = this.props.navigation.addListener(
'didFocus',
() => { console.log('did focus') },
);
}
componentWillUnmount() {
this.didFocusListener.remove();
}
render() {
return ( /* your render */ );
}
}
And then in the case you are on Main and you are navigating to your Profile route. You should set a params in the navigation to say that the previous route is Main.
Route parameters: navigation.navigate('Profile', { previous_screen: 'Main' });
So now in your willFocus listener:
if the previous_screen param is set, it means that you don"t have to do anything.
If not, means that you come from the other tab and that it will navigate to the wrong route. So you can either reset you're navigation route or just navigate to the 'Profile' route.
NOTE:
I didn't try this solution and maybe the transition animation is not going to be smooth. So tell me if it does the job well or not.

Categories

Resources