I am new to react native. I have been using createStackNavigator to be able to navigator throughout my app.
I have created a number of different stacks. Within each stack I have my header code. I have a button in each header that I want to be able to press in order to navigate to another screen, however this screen is within another stack. How would I get access to it?
Here is my code.
export const SearchStack = createStackNavigator({
Search: {
screen: SearchScreen
});
export const HomeStack = createStackNavigator({
Home:
{
screen: HomeScreen,
navigationOptions: ({ navigation }) => ({
headerTitle: 'Home',
headerRight: (
<Icon name="ios-search" color="#fff" size={30} style={{paddingRight: 20}}
onPress={() => navigation.navigate('SearchStack', {}, NavigationActions.navigate({ routeName: 'Search'}))} />
),
headerTitleStyle:{
color: "white",
alignSelf: "center",
fontSize: 20
},
headerStyle:{
backgroundColor: "#404042"
}
}),
},
Listen: {
screen: MainScreen,
navigationOptions: {
headerTitle: 'Listen',
headerRight: (
<Icon name="ios-search" color="#fff" size={30} style={{paddingRight: 20}}
onPress={() => navigation.navigate('Search')} />
),
headerTitleStyle:{
color: "white",
alignSelf: "center",
fontSize: 20
},
headerStyle:{
backgroundColor: "#404042"
}
}
},
},
});
Normally you can call any screen you want as long it is in one of the stacks.
What is the best way to implement the logout functionality in react native in my case when i click the logout button it works fine but next time when i again login and click it it does not work.
import React, {Component} from 'react';
import {AsyncStorage} from 'react-native';
import {url} from '../globals';
import Toast from 'react-native-simple-toast';
class Logout extends Component {
constructor(props) {
super(props);
this.onLogOutPressed = this.onLogOutPressed.bind(this);
}
static navigationOptions = {
header: null,
};
componentWillMount() {
this.onLogOutPressed();
this.props.navigation.addListener('willFocus', this.onLogOutPressed);
}
async onLogOutPressed() {
try {
let response = await fetch(url + '/auth/Logout', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
if (response.status >= 200 && response.status < 300) {
console.log('Request Status ', response.status);
let res = await response.json();
console.log('Logout response:', res);
Toast.showWithGravity(res, Toast.LONG, Toast.CENTER);
await AsyncStorage.clear();
this.props.navigation.navigate('login');
} else {
throw 'Enable to parse';
}
} catch (error) {
console.log('error ' + error);
}
}
render() {
return null;
}
}
export default Logout;
And this is the stack navigator and drawer navigation when i click on the logout button for the first time it work fine but second time it move to me last visited page
import React, {Component} from 'react';
import {
StyleSheet,
Dimensions,
SafeAreaView,
View,
Text,
ScrollView,
Image,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import Login from './src/pages/Login';
import Companies from './src/admin/Companies';
import LicensesTable from './src/admin/VerifyLicenses';
import EditLicense from './src/admin/EditLicense';
import ActionEdit from './src/admin/EditLicenseDetails';
import PricingPlan from './src/admin/PricingPlan';
import {createStackNavigator} from 'react-navigation-stack';
import {createDrawerNavigator, DrawerItems} from 'react-navigation-drawer';
import {createSwitchNavigator, createAppContainer} from 'react-navigation';
import AdmDash from './src/admin/AdminDashboard';
import Users from './src/admin/Users';
import Logout from './src/pages/Logout';
global.currentScreenIndex = 0;
export default class App extends Component {
render() {
console.disableYellowBox = true;
return <Draw />;
}
}
const CompaniesStackNavigator = createStackNavigator(
{
CompaniesNavigator: {screen: Companies},
},
{
defaultNavigationOptions: ({navigation}) => {
return {
title: 'Companies',
headerStyle: {backgroundColor: '#1D60D2'},
headerTintColor: 'white',
headerLeft: (
<Icon
style={{paddingLeft: 10, color: 'white'}}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
),
};
},
},
);
const PricingStackNavigator = createStackNavigator(
{
PricingNavigator: {screen: PricingPlan},
},
{
defaultNavigationOptions: ({navigation}) => {
return {
title: 'Pricing Plan',
headerStyle: {backgroundColor: '#1D60D2'},
headerTintColor: 'white',
headerLeft: (
<Icon
style={{paddingLeft: 10, color: 'white'}}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
),
};
},
},
);
const UserStackNavigator = createStackNavigator(
{
UserNavigator: Users,
},
{
defaultNavigationOptions: ({navigation}) => {
return {
title: 'Users',
headerStyle: {backgroundColor: '#1D60D2'},
headerTintColor: 'white',
headerLeft: (
<Icon
style={{paddingLeft: 10, color: 'white'}}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
),
};
},
},
);
const DashboardStackNavigatorAdmin = createStackNavigator(
{
DashboardNavigator: {screen: AdmDash},
},
{
defaultNavigationOptions: ({navigation}) => {
return {
title: 'Dashboard',
headerStyle: {backgroundColor: '#1D60D2'},
headerTintColor: 'white',
headerLeft: (
<Icon
style={{paddingLeft: 10, color: 'white'}}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
),
};
},
},
);
const LicensesStackNavigator = createStackNavigator(
{
LicensesNavigator: {screen: LicensesTable},
},
{
defaultNavigationOptions: ({navigation}) => {
return {
title: 'Verify Licenses',
headerStyle: {backgroundColor: '#1D60D2'},
headerTintColor: 'white',
headerLeft: (
<Icon
style={{paddingLeft: 10, color: 'white'}}
onPress={() => navigation.openDrawer()}
name="md-menu"
size={30}
/>
),
};
},
},
);
const LogoutStackNavigator = createStackNavigator({
LogOutNAvigator: {
screen: Logout,
},
});
const AppNavigator = createStackNavigator({
login: {screen: Login},
EditLicense: {screen: EditLicense},
ActionEdit: {screen: ActionEdit},
},
{
initialRouteName: "login"
});
const AppDrawerNavigator = createDrawerNavigator(
{
login: {
screen: AppNavigator,
navigationOptions: {
drawerLabel: () => null,
},
},
Home: {
screen: DashboardStackNavigatorAdmin,
navigationOptions: {
drawerLabel: () => 'Dashboard',
drawerIcon: ({tintColor}) => (
<Icon name="md-home" style={{fontSize: 24, color: tintColor}} />
),
},
},
Users: {
screen: UserStackNavigator,
navigationOptions: {
drawerIcon: ({tintColor}) => (
<Icon name="md-person" style={{fontSize: 24, color: tintColor}} />
),
},
},
'Pricing Plan':{
screen:PricingStackNavigator,
navigationOptions: {
drawerIcon: ({tintColor}) => (
<Icon name="md-pricetag" style={{fontSize: 24, color: tintColor}} />
),
},
},
Licenses: {
screen: LicensesStackNavigator,
navigationOptions: {
drawerIcon: ({tintColor}) => (
<Icon name="md-briefcase" style={{fontSize: 24, color: tintColor}} />
),
},
},
Companies: {
screen: CompaniesStackNavigator,
navigationOptions: {
drawerIcon: ({tintColor}) => (
<Icon name="md-card" style={{fontSize: 24, color: tintColor}} />
),
},
},
Logout: {
screen: LogoutStackNavigator,
navigationOptions: {
drawerIcon: ({tintColor}) => (
<Icon name="md-log-out" style={{fontSize: 24, color: tintColor}} />
),
},
},
},
{
contentComponent: props => (
<SafeAreaView style={styles.container}>
<View>
<Image
source={require('./src/Images/download.png')}
style={styles.sideMenuProfileIcon}
/>
<Text></Text>
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView>
</SafeAreaView>
),
drawerWidth: Dimensions.get('window').width - 130,
},
);
const AppSwitchNavigator = createSwitchNavigator({
Dashboard: {screen: AppDrawerNavigator},
Users: {screen: Users},
Companies: {screen: Companies},
Licenses: {screen: LicensesTable},
});
const Draw = createAppContainer(AppSwitchNavigator);
const styles = StyleSheet.create({
IconS: {
paddingLeft: 10,
},
HeaderStyle: {
backgroundColor: '#1D60D2',
},
container: {
flex: 1,
alignContent: 'center',
justifyContent: 'center',
},
sideMenuContainer: {
width: '100%',
height: '100%',
backgroundColor: '#fff',
alignItems: 'center',
paddingTop: 20,
},
sideMenuProfileIcon: {
resizeMode: 'center',
width: 150,
height: 150,
marginTop: 20,
borderRadius: 75,
alignContent: 'center',
justifyContent: 'center',
},
});
I realise logout in Drawer without conponent, simple overload onItemPress (Typescript example):
<DrawerItems
{...props}
items={props.items.filter((i: any) => i.key !== 'UserProfile')}
getLabel={({route}: Scene) => {
const title = props.descriptors[route.key].options.title;
return (
<Text
style={
route.key !== 'Logout'
? styles.labelStyle
: styles.labelExitStyle
}>
{t(title)}
</Text>
);
}}
//labelStyle={styles.labelStyle}
itemStyle={styles.itemStyle}
iconContainerStyle={styles.iconOpacity}
onItemPress={({route}) => {
if (route.key === 'Logout') {
Alert.alert(
t('Logout'),
t('Are you sure you want to logout?'),
[
{
text: t('Ok'),
onPress: async () => {
const result = await clearProfile();
if (result) {
navigate('Choose');
}
},
},
{text: t('Cancel'), style: 'cancel'},
],
{
cancelable: false,
},
);
} else {
navigate(route.key);
}
}}
/>
It's your Darwer menu:
createDrawerNavigator(
{
...
Logout: {
screen: Choose,
navigationOptions: {
title: 'Logout',
drawerIcon: <Image source={iconRedExit} style={styles.icon} />,
},
},
},
{
initialRouteName: 'Tests',
contentComponent: CustomDrawer,
drawerWidth: width,
},
),
In your CustomDrawer render() you can use DrawerItems from my answer
I made a toggler menu by createDrawerNavigator. at first the menu was working perfectly but after making each page i realized it doesnt scroll verticaly as same before. i dont understand what the problem is. in addtion when each page has error, after clicking on that page the app freezes and menu do scroll! any help? many thanks
.see the menu here https://i.stack.imgur.com/FwoqI.jpg
//imports;
class NavigationDrawerStructure extends React.Component {
toggleDrawer = () => {
this.props.navigationProps.toggleDrawer();
};
render() {
return (
<View style={{ flex: 1 }}>
<TouchableOpacity onPress={this.toggleDrawer.bind(this)}>
<Image
source={require('./image/drawer.png')}
style={{ width: 30, height: 30, marginLeft: 20, marginBottom:10 }}
/>
</TouchableOpacity>
</View>
);
}
}
const firstScreen = createStackNavigator({
Data: {
screen: Data,
navigationOptions: ({ navigation }) => ({
title: 'Data',
headerLeft: <NavigationDrawerStructure navigationProps={navigation} />,
headerStyle: {
backgroundColor: '#fff',
},
headerTintColor: 'black',
}),
},
});
const screensDrawerNavigator = createDrawerNavigator(
{
Data: {
screen: firstScreen,
navigationOptions: {
drawerLabel: 'Data',
},
},
},
{
intialRouteName: 'login',
navigationOptions: {
headerStyle : {
backgroundColor: '#f4511e',
},
color: 'white',
},
},
}
)
export default createAppContainer(screensDrawerNavigator);
[1]: https://i.stack.imgur.com/FwoqI.jpg
according the doc's it seems that you are not able to scroll by default because there is no scrollview component added by default. maybe you can try to add a custom-component from this example: https://reactnavigation.org/docs/en/drawer-navigator.html
I think in your case it would be similar to this (see contentComponent):
const screensDrawerNavigator = createDrawerNavigator(
{
Data: {
screen: firstScreen,
navigationOptions: {
drawerLabel: 'Data',
},
},
},
{
intialRouteName: 'login',
contentComponent: props => (
<ScrollView>
<SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
),
navigationOptions: {
headerStyle : {
backgroundColor: '#f4511e',
},
color: 'white',
},
},
)
I have a Drawer navigation and stack navigation on my app.
export const AppDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: Home,
navigationOptions: {
drawerIcon: ({ tintColor }) => (
<Icon name="home" style={{ fontSize: 24, color: tintColor }} />
)
}
},
MyAccount: {
screen: MyAccount,
navigationOptions: {
drawerIcon: ({ tintColor }) => (
<Icon name="paper" style={{ fontSize: 24, color: tintColor }} />
)
}
},
Cashback: {
screen: Cashback,
navigationOptions: {
drawerIcon: ({ tintColor }) => (
<Icon name="pizza" style={{ fontSize: 24, color: tintColor }} />
)
}
},
Settings: {
screen: Settings,
navigationOptions: {
drawerIcon: ({ tintColor }) => (
<Icon name="settings" style={{ fontSize: 24, color: tintColor }} />
)
}
},
Campaigns: {
screen: Campaigns,
navigationOptions: {
drawerIcon: ({ tintColor }) => (
<Icon name="call" style={{ fontSize: 24, color: tintColor }} />
)
}
}
},
{
contentComponent: CustomDrawerComponent,
contentOptions: { activeTintColor: "#60c2a2" }
}
);
export const AppStackNavigator = createStackNavigator(
{
OnBoarding: {
screen: OnBoardingContent
},
Login: {
screen: Login
},
MarchantLogin: {
screen: MarchantLogin
},
OTPScreen: {
screen: OTPScreen
},
Home: {
screen: Home
},
Drawer: {
screen: AppDrawerNavigator
}
},
{
headerMode: "none",
initialRouteName: "Drawer",
navigationOptions: {
headerVisible: false
}
}
);
Then I call this on
render() {
if (this.state.is_verified == "true") {
return <AppStackNavigator />;
} else {
return <OnBoarding />;
}
}
My problem is that when I click on logout inside Drawer button I need to route to OnBoarding component. But how is it possible?
Please help me to solve this or suggest me a better idea because I'm new to this stack. Thankyou.
I am overlapping a StackNavigator on a DrawerNavigator. This is my code
const AppNavigator = StackNavigator({
Home: {
screen: WelcomeContainer,
navigationOptions: ({navigation}) => ({
headerLeft:
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems:'center'}}>
<Icon name="menu" color='#5c72b0' size={35} style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems:'center',
paddingLeft:10,
paddingRight:80 }} onPress={ () => navigation.navigate('DrawerOpen') } />
<ChangeLanguage style={{ margin: 30 , padding: 30}} />
</View>,
headerRight:
<HeaderUserInformation />,
})
},
Settings: {
screen: SettingsContainer,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title
})
},
About: {
screen: About,
navigationOptions: ({navigation}) => ({
title: navigation.state.params.title
})
}
})
const AppDrawer = DrawerNavigator({
Home: {
screen:StackNavigator({
Home: {
screen: WelcomeContainer,
navigationOptions: {
}
}
})
},
Settings: {
screen: StackNavigator({
Category: {
screen: SettingsContainer,
navigationOptions: {
title: "Settings"
}
}
})
}
})
The drawer works properly but there is a problem with the header. This was not the case before I embed the StackNavigator on the DrawerNavigator. The problem is that I customized the header by adding buttons and I am not seeing them anymore on the header. And When I navigate to a new Screen I am not seeing the back button on the header anymore. Do you have an idea what could the problem be?