Drawer Navigator doesnt scroll after making other pages - reactjs

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',
},
},
)

Related

How to navigate between different nested stacks in react navigation - react native

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.

How to implement Log out Functionality in react native

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

React native: header styles in navigationOptions not working

I am fairly new to react-native. I am trying to set some global header styles for my app, but it's not working
route.js
import React, { Component } from 'react';
import { View } from 'react-native';
import { createStackNavigator, createAppContainer } from "react-navigation";
import SplashScreen from '../screens/SplashScreen';
import CalendarScreeen from '../screens/CalendarScreen';
const NavStack = createStackNavigator(
{
Splash: {
screen: SplashScreen,
navigationOptions: {
header: null
},
},
Calendar: {
screen: CalendarScreeen,
navigationOptions: {
title: 'Calendar',
},
},
},
{
initialRouteName: 'Calendar',
navigationOptions: {
headerStyle: {
backgroundColor: '#28F1A6',
elevation: 0,
shadowOpacity: 0
},
headerTintColor: '#333333',
headerTitleStyle: {
fontWeight: 'bold',
color: '#ffffff'
}
}
}
);
const Routes = createAppContainer(NavStack);
export default Routes;
Now, I am aware that I can do something like this in my class component
static navigationOptions = {
title: 'Chat',
headerStyle: { backgroundColor: 'red' },
headerTitleStyle: { color: 'green' },
}
as it is mentioned in here possible alternative
but I want to achieve the same from my route.js
I also tried defaultNavigationOptions like its mentioned in docs
But no luck!!
I think you are using react navigation version 3. If so navigationOptions is changed to defaultNavigationOptions.
{
initialRouteName: 'Calendar',
defaultNavigationOptions: {
headerStyle: {
backgroundColor: '#28F1A6',
elevation: 0,
shadowOpacity: 0
},
headerTintColor: '#333333',
headerTitleStyle: {
fontWeight: 'bold',
color: '#ffffff'
}
}
}
It should work. https://snack.expo.io/ByGrHdAC7
You need to use defaultNavigationOptions.
Admittedly, they didn't even mention that they changed it between v2 and v3 in the docs!
https://reactnavigation.org/docs/en/stack-navigator.html
to setup custom react react navigation you need first defined option.navigations or option.defaultNavigationOptions in your App.js
App.js
<Stack.Screen
name="ListeMedocItemScreen"
component={ListeMedocItemScreen}
options={ListeMedocItemScreen.defaultNavigationOptions} // ListeMedocItemScreen.navigationOptions
/>
then in your conponents page
if you use hooks
const ListeMedocItem = (props) =>{
//some component
}
ListeMedocItem.defaultNavigationOptions = ({navigation}) => {
return {
title: 'My home',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
or if you use React.Components
static navigationOptions = ({ navigation }) => {
//return header with Custom View which will replace the original header
return {
header: (
<View
style={{
height: 45,
marginTop: 20,
backgroundColor: 'red',
justifyContent: 'center',
}}>
<Text
style={{
color: 'white',
textAlign: 'center',
fontWeight: 'bold',
fontSize: 18,
}}>
This is Custom Header
</Text>
</View>
),
};
};
Just simply change your navigationOptions to defaultNavigationOptions and it will work fine
Thankx!
elevation: 0 in Android 10 doesnt work. Others Android version it works.
It is changes to transparent header.

Drawer header not overlapping StackNavigator header

I am using a DrawerNavigator header and a stack navigation. When the drawer is open, it dose not overlap the header. This is my code
const AppDrawer = DrawerNavigator(
{
Home: {
path: '/',
screen: WelcomeContainer,
},
Category: {
path: '/sent',
screen: CategoryContainer,
},
},
{
initialRouteName: 'Home',
contentOptions: {
activeTintColor: '#e91e63',
},
}
);
const AppNavigator = StackNavigator({
Home: {
screen: AppDrawer,
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
})
}
})
I found different threads with the same problem. I tried to move DrawNavigator to the top level, my code become :
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: {
path: '/',
screen: AppNavigator,
},
Category: {
path: '/sent',
screen: CategoryContainer,
},
},
{
initialRouteName: 'Home',
contentOptions: {
activeTintColor: '#e91e63',
},
}
);
Now the drawer is overlapping the header, however the header disappeared from the other components: If I click on an element on the drawer, for example settings, there is no header anymore on this screen. How can I properly fix this overlapping problem?
The DrawerNavigator must be the outermost navigator in order for it to overlap the header, and each screen inside must be declared inside a StackNavigator, like below
const AppDrawer = DrawerNavigator({
Home: {
screen: StackNavigator({
Home: {
screen: WelcomeContainer,
navigationOptions: {
title: "Welcome"
}
}
})
},
Category: {
screen: StackNavigator({
Category: {
screen: CategoryContainer,
navigationOptions: {
title: "Category"
}
}
})
}
})

Header dose not appearing when using a drawer

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?

Resources