Reputation: 91
I've been searching for a simple solution with best practices to have drawer that would show user's info, i.e. name, age, etc. The login will happen in a separate screen but after the login is done, somehow user info should be passed to drawerNavigator. DrawerNav - StackNav - Screen1 - Screen2 - SettingsScreen (login will happen here)
It's really frustrating that I couldn't find a working solution yet. Expo code: https://snack.expo.io/@alisalimi25/user-info-drawer
import React, { Component } from 'react';
import {
Button,
SafeAreaView,
ScrollView,
Text,
View
} from 'react-native';
import {
createDrawerNavigator, createStackNavigator,
DrawerItems, NavigationActions
} from 'react-navigation';
class Screen2 extends React.Component {
render() {
return(
<View><Text>Screen2</Text></View>
);
}
}
class Screen1 extends React.Component {
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Text>Screen1</Text>
<Button
onPress={() => this.props.navigation.openDrawer()}
title='Open Drawer' />
</SafeAreaView>
);
}
}
class SettingScreen extends React.Component {
loginUser = () => {
console.log('We need to pass user info into drawer navigator');
};
render() {
return (
<SafeAreaView>
<Text>Settings Page</Text>
<Button
onPress={() => this.loginUser()}
title='Login' />
</SafeAreaView>
);
}
}
const StackNav = createStackNavigator(
{
Screen1: Screen1,
Screen2: Screen2
}
);
const CustomDrawerContentComponent = (props) => {
return (
<ScrollView>
<SafeAreaView style={{ flex: 1 }} forceInset={{ top: 'always', horizontal: 'never' }}>
<Text>Hello USER_NAME_FROM_PROPS?</Text>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
)
};
const DrawerNav = createDrawerNavigator(
{
StackNav: {
screen: StackNav,
},
SettingScreen: {
screen: SettingScreen
}
},
{
contentComponent: CustomDrawerContentComponent
}
);
export default DrawerNav;
I'm sure the solution is somewhere but I couldn't find it yet. Any help is highly appreciated.
Thanks
Upvotes: 0
Views: 1839
Reputation: 91
So I managed to use screenProps to pass around parameters between pages but I'm not sure if it's a good pattern because it's like global variables and I think there is a chance of name collision between different layers of navigation. The working code is: import React, { Component } from 'react'; import { Button, SafeAreaView, ScrollView, Text, View } from 'react-native';
import {
createDrawerNavigator, createStackNavigator,
DrawerItems, NavigationActions
} from 'react-navigation';
class Screen2 extends React.Component {
render() {
return(
<View><Text>Screen2</Text></View>
);
}
}
class Screen1 extends React.Component {
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Text>Screen1</Text>
<Button
onPress={() => this.props.navigation.openDrawer()}
title='Open Drawer' />
</SafeAreaView>
);
}
}
class SettingScreen extends React.Component {
constructor(props) {
super(props);
console.log('passed props for settingScreen are: ', props);
}
loginUser = () => {
console.log('We need to pass user info into drawer navigator');
this.props.screenProps.userId = 'Gandalf';
};
render() {
return (
<SafeAreaView>
<Text>Settings Page</Text>
<Button
onPress={() => this.loginUser()}
title='Login' />
</SafeAreaView>
);
}
}
const StackNav = createStackNavigator(
{
Screen1: Screen1,
Screen2: Screen2
}
);
const CustomDrawerContentComponent = (props) => {
console.log('props in custom component are: ', props);
return (
<ScrollView>
<SafeAreaView style={{ flex: 1 }} forceInset={{ top: 'always', horizontal: 'never' }}>
<Text>Hello {props.screenProps.userId}</Text>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
)
};
const DrawerNav = createDrawerNavigator(
{
StackNav: {
screen: StackNav,
},
SettingScreen: {
screen: SettingScreen
}
},
{
contentComponent: CustomDrawerContentComponent
}
);
class DrawerNavWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
loggedInUser: {
}
};
}
render() {
return(
<DrawerNav screenProps={this.state.loggedInUser} />
);
}
}
export default DrawerNavWrapper;
After "Login" button is pressed in SettingScreen, screenProps is set this.props.screenProps.userId = 'Gandalf'; and when you open drawer, "Hello Gandalf" will be shown.
The other solution is to use JS Modules. Or maybe use react context (https://github.com/react-navigation/react-navigation/issues/4511)
Anyone knows a better solution?
Thanks
Upvotes: 1