How to add Custom Sidemenu in Existing Home Page - reactjs

In my React Native app Code, i used StackNavigator for Storing Splash Screen, Login Screen, and Home Screen. In that Home Screen i want to add a SideMenu whenever Click a Icon in the Top Right Corner of the Page.
I searched many Drawer Navigator examples. In that examples the side menu is added in Left/Right side of the default header.But in my case, I just create a top bar and in that bar I include Logo, SearchBar Input, Logout Icon,History Icon and Finally the SideMenu Icon.
// Index Page
//import App from './App';
import { name as appName } from './app.json';
import { createAppContainer } from 'react-navigation'
import { createStackNavigator } from 'react-navigation-stack'
import Splash from './src/components/Splash'
import Login from './src/components/Login'
import Home from './src/components/Home'
const MainNavigator = createStackNavigator({
Splash: {
screen: Splash
},
Login: {
screen: Login
},
Home: {
screen: Home
}
},
{
navigationOptions: {
header: null
}
}
);
const Apps = createAppContainer(MainNavigator)
AppRegistry.registerComponent(appName, () => Apps);
HomePage render()
<View style={styles.backgroundcontainer}>
{/* Top Bar */}
<View style={styles.navBar}>
<View style={styles.leftNav}>
<Image source={require('../images/logo2.png')} style={{ width: 75, height: 55, borderRadius: 26 }} />
</View>
<View style={styles.middleNav}>
<TextInput style={styles.input}
placeholder='Enter Item to Search..'
//placeholderTextColor='rgba(255,255,255, 0.7)'
returnKeyType={"next"}
underlineColorAndroid='transparent'
value={this.state.search_keyword}
onChangeText={(search_keyword) => this.setState({ search_keyword })}
/>
<TouchableOpacity style={{ alignItems: 'center' }} onPress={() => this.getSearchResult(this.state.search_keyword)}>
<Icon name="magnify" size={40} color={'#00bfff'} />
</TouchableOpacity>
</View>
<View style={styles.rightNav}>
{/* <TouchableOpacity style={{ borderBottomColor: 'black' }}>
<Text style={{ fontSize: 22, textAlign: 'center', fontWeight: 'bold' }}>Sign In</Text>
</TouchableOpacity> */}
<TouchableOpacity onPress={() => this.logout()}>
<Icon name="logout" size={25} style={styles.navItem} />
</TouchableOpacity>
<TouchableOpacity>
<Icon name="clipboard-outline" size={25} color={'#00bfff'} style={styles.navItem} />
</TouchableOpacity>
<TouchableOpacity>
<Icon name="menu" size={25} color={'#00bfff'} style={styles.navItem} />
</TouchableOpacity>
</View>
</View>
</View>
package.json
react": "16.9.0",
"react-native": "0.61.2",
"react-native-gesture-handler": "^1.4.1",
"react-native-vector-icons": "^6.6.0",
"react-navigation": "^4.0.10",
"react-navigation-stack": "^1.9.4"
Expected behaviour is When I click the SideMenu Icon the Sidemenu will open. But I don't have any idea for creating such a Custom Side Menu.
[HomePage] https://imgur.com/oNbURU8
[Expected Image] https://imgur.com/LjBEyrf

Create a Drawer Route on top of your navigation routes like this
const MyDrawerNavigator = createDrawerNavigator({
Home: {
screen: MainNavigator,
},
});
const MyApp = createAppContainer(MyDrawerNavigator);
and pass your main navigator as a route.
const MainNavigator = createStackNavigator({
Splash: {
screen: Splash
},
Login: {
screen: Login
},
Home: {
screen: Home
}
},
{
navigationOptions: {
header: null
}
}
);

You will have to use react-navigation-drawer for it.
//import App from './App';
import { name as appName } from './app.json';
import { createAppContainer } from 'react-navigation'
import { createStackNavigator } from 'react-navigation-stack'
import { createDrawerNavigator } from 'react-navigation-drawer'
import Splash from './src/components/Splash'
import Login from './src/components/Login'
import Home from './src/components/Home'
const HomeStack = createDrawerNavigator({
Home: {
screen: Home,
},
{
navigationOptions: {
header: null
}
}
});
const MainNavigator = createStackNavigator({
Splash: {
screen: Splash
},
Login: {
screen: Login
},
Home: HomeStack
},
{
navigationOptions: {
header: null
}
}
);
const Apps = createAppContainer(MainNavigator)
AppRegistry.registerComponent(appName, () => Apps);
Then update the menu button for opening the drawer like
<TouchableOpacity onPress={this.props.navigation.toggleDrawer)}>
<Icon name="menu" size={25} color={'#00bfff'} style={styles.navItem} />
</TouchableOpacity>
For more information https://reactnavigation.org/docs/en/drawer-navigator.html

Related

Switch navigator does not works in React Native

I've asked a question already, and modified as much as I can, but still in trouble.
Combined all children Screen js files into App.js
When I compile and run, App shows LoginScreen.js, not LoadingScreen.js.
Also, onPress={this.props.navigation.navigate('Loading')} does not works. If I press the button, it shows nothing.
What am I still missing?
import React from 'react'
import { StyleSheet, Platform, Image, Text, View, TextInput, Button, ActivityIndicator } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
class LoadingScreen extends React.Component {
render() {
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={this.props.navigation.navigate('Login')} />
</View>
)
}
}
class LoginScreen extends React.Component {
state = { email: '', password: '' }
render() {
return (
<View style={styles.logincontainer}>
<Button
title='Sign in' onPress={this.props.navigation.navigate('Loading')}
/>
<Button
title='Sign Up'
/>
</View>
)
}
}
const styles = StyleSheet.create({
loadingcontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logincontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logintextInput: {
height: 40,
width: '90%',
borderColor: 'gray',
borderWidth: 1,
marginTop: 8
},
})
const App = createSwitchNavigator(
{
Loading: {
screen: LoadingScreen,
},
Login: {
screen: LoginScreen,
},
}
);
export default createAppContainer(App);
Thank you for your help.
For just navigation, you can use a stack navigator. The switch navigator used for conditional rendering of two different stacks. Anyways you can set loading as the first screen buy setting initialRouteName to loading. Here is an example
createSwitchNavigator(
{
LimitedAccess: {
screen: Trial,
},
AppScreens: {
screen: AppScreens,
},
AuthScreens: {
screen: AuthScreens,
},
},
{
initialRouteName: signedIn ? 'AppScreens' : 'AuthScreens',
},
),
);
Note: Here signedIn is a conditional operator which decides the rendering of stacks.
The way your props are currently defined causes them to be instantly executed.
The onPress prop is instantly executed.
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={this.props.navigation.navigate('Login')} />
</View>
)
You should instead attach a function to onPress that can be executed when the button is pressed.
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={() => this.props.navigation.navigate('Login')} />
</View>
)
Your onPress-calls are running instantly, which causes your problems.
Change to:
import React from 'react'
import { StyleSheet, Platform, Image, Text, View, TextInput, Button, ActivityIndicator } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { createBottomTabNavigator } from 'react-navigation-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
class LoadingScreen extends React.Component {
render() {
return (
<View style={styles.loadingcontainer}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
<Button title="Move to LoginScreen" onPress={() => this.props.navigation.navigate('Login')} />
</View>
)
}
}
class LoginScreen extends React.Component {
state = { email: '', password: '' }
render() {
return (
<View style={styles.logincontainer}>
<Button
title='Sign in' onPress={() => this.props.navigation.navigate('Loading')}
/>
<Button
title='Sign Up'
/>
</View>
)
}
}
const styles = StyleSheet.create({
loadingcontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
logincontainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
logintextInput: {
height: 40,
width: '90%',
borderColor: 'gray',
borderWidth: 1,
marginTop: 8
},
})
const App = createSwitchNavigator(
{
Loading: {
screen: LoadingScreen,
},
Login: {
screen: LoginScreen,
},
}
);
export default createAppContainer(App);

React native createDrawerNavigator is not working

Could you please help me on this small issue.
I am very very new to React native and here i am training in learn react navigation. My problem is Drawer navigator is not working when i try to swap from left to right. But bottom navigator is working. Any idea whats wrong with this please.
Also: if you can please send me a good sample to learn this area.
I have some samples, but most of the samples are outdated.
MyCode:
import React from 'react';
import {TouchableOpacity, View, Text, Image} from 'react-native';
import {createAppContainer, createSwitchNavigator} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
import {createBottomTabNavigator} from 'react-navigation-tabs';
import {createDrawerNavigator} from 'react-navigation-drawer';
import HomeScreen2 from '../screens/HomeScreen2';
import HomeScreen from '../screens/HomeScreen';
import Setup from '../screens/Setup';
const HomeStack = createStackNavigator(
{
//Defination of Navigaton from home screen
Home: { screen: HomeScreen },
// Details: { screen: ProfileScreen },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Home',
//Header title
},
}
);
const SettingsStack = createStackNavigator(
{
//Defination of Navigaton from setting screen
Settings: { screen: Setup },
},
{
defaultNavigationOptions: {
//Header customization of the perticular Screen
headerStyle: {
backgroundColor: '#42f44b',
},
headerTintColor: '#FFFFFF',
title: 'Settings',
//Header title
},
}
);
const TabMain = createBottomTabNavigator(
{
TAB1: HomeStack,
TAB2: SettingsStack,
},
{
initialRouteName: 'TAB1',
}
)
const DrawHomeView = createStackNavigator({
HomeV: {screen: HomeScreen2}},
{
headerMode: 'float',
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: 'rgb(255,45,85)',
paddingLeft: 10,
paddingRight: 10
},
title: 'Map View',
headerTintColor: 'white',
headerLeft: <View>
<TouchableOpacity
onPress={() => {
if (navigation.state.isDrawerOpen === false) {
navigation.dispatch(DrawerActions.openDrawer());
} else {
navigation.dispatch(DrawerActions.closeDrawer());
}
}}>
<Text>Menu</Text>
</TouchableOpacity>
</View>
})
});
const DrawSettingsView = createStackNavigator({
SettingsV: {screen: Setup}},
{
headerMode: 'float',
navigationOptions: ({navigation}) => ({
headerStyle: {
backgroundColor: 'rgb(255,45,85)',
paddingLeft: 10,
paddingRight: 10
},
title: 'Map View',
headerTintColor: 'white',
headerLeft: <View>
<TouchableOpacity
onPress={() => {
if (navigation.state.isDrawerOpen === false) {
navigation.dispatch(DrawerActions.openDrawer());
} else {
navigation.dispatch(DrawerActions.closeDrawer());
}
}}>
<Text>Menu</Text>
</TouchableOpacity>
</View>
})
});
const TabMain2 = createDrawerNavigator(
{
TAB3: DrawHomeView,
TAB4: DrawSettingsView,
},
{
initialRouteName: 'TAB3',
}
)
export default createAppContainer(createSwitchNavigator(
{
Sub1: TabMain,
Sub2: TabMain2,
},
{
initialRouteName: 'Sub2',
}
));
Okay. After some dabbling with your code and the docs : https://reactnavigation.org/docs/nesting-navigators/
and please read the docs and try their examples as they are excellent descriptive and available for real time execution on snack.
For the second part of the question, i put together an example for you:
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
//Import necessary components
//Create Screens, Dummy screens in this case.
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
function Feed ({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 40}}>Feed </Text>
</View>
);}
function Home ({ navigation, route }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text style={{fontSize: 40}}> Home </Text>
</View>
);}
// Here is your questions answer, just create a Bottom Navigator
// and a Drawer Navigator and nest them in each other after declaring your
// screens.
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
function HomeScreen({ navigation }) {
return (
<Tab.Navigator>
//Put your Tab screens here.
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Feed" component={Feed} />
</Tab.Navigator>
);
}
export default function App() {
return (
// For the main export create a navigation container and declare the
// Drawer Navigator inside the main navigation container, then use that to
// To Access your Tab navigator "HomeScreen" and put whatever else you
// Want in your Drawer Navigator.
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Explanation: You are only allowed to nest navigators within each other and not within the main navigation container.
This code has been tested using expo-cli 3.18.4

React Navigation drawer goes blank after adding contentComponent

I am using React Navigation to create custom NavigationDrawer with a header on top this is how my code looks
import React, { Component } from "react";
import { View, Text, StyleSheet } from "react-native";
import AboutScreen from './modules/screens/About/index'
import ContactScreen from './modules/screens/Contact/index'
import HomeScreen from './modules/screens/Home/index'
import { createDrawerNavigator, DrawerItems } from "react-navigation";
import { Image, ScrollView, SafeAreaView, Dimensions } from 'react-native';
class NewDrawer extends Component {
render() {
return (
<AppDrawer />
);
}
}
const AppDrawer = createDrawerNavigator({
HomeScreen: HomeScreen,
AboutScreen: AboutScreen,
ContactScreen: ContactScreen,
},
//Commenting below part makes my code work
{
contentComponent: CustomDrawer
}
)
const CustomDrawer = (props) => (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ height: 150, backgroundColor: 'white' }}>
<Image source={require('./modules/images/header.jpeg')}
style={{ height: 120, width: 120 }}>
</Image>
</View>
<ScrollView>
<DrawerItems {...props}>
</DrawerItems>
</ScrollView>
</SafeAreaView>
)
export default NewDrawer;
If I remove contentComponent i see my drawer items.
How can I get Header with custom drawer item?
I am using:-
npm > v6.4.1
Node > v8.12.0
react-navigation > v2.17.0
I am following this tutorial
You are not sending props to CustomDrawer . Try code below.
contentComponent: props => <CustomDrawer {...props} />
Drawer.js
<SafeAreaView style={{ flex: 1 }}>
<View style={{ height: 150, backgroundColor: 'white' }}>
<Image source={require('./modules/images/header.jpeg')}
style={{ height: 120, width: 120 }}>
</Image>
</View>
<ScrollView>
<DrawerItems {...props}>
</DrawerItems>
</ScrollView>
</SafeAreaView>
App.js
import CustomDrawer from './Drawer' // Import the file
const AppDrawer = createDrawerNavigator({
HomeScreen: HomeScreen,
AboutScreen: AboutScreen,
ContactScreen: ContactScreen,
},
{
contentComponent: <CustomDrawer />
}
)
This should work tested on android device

React Native Navigation Open Draw From Header Button

I'm trying to open a navigation draw from a stack navigation header button. The header button is showing up fine but when I click the button I am getting
undefined is not an object (evaluating '_this.props.navigate')
I can't seem to find a solid example of how to do this or if its even possible with react navigation.
import React, { Component } from 'react';
import { createStackNavigator, NavigationActions } from 'react-navigation'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { Draw } from './DrawNav.js'
export const RootStack = createStackNavigator (
{
DrawNav: {
screen: Draw,
navigationOptions: ({ navigation }) => ({
//Hide the shadow of the header
headerStyle: {
elevation:0,
shadowColor: 'transparent',
shadowRadius: 0,
shadowOffset: {
height: 0,
}
},
headerLeft: (
<View style={{marginLeft: 10}}>
<Icon
name="menu"
size={25}
color="#D4AF37"
onPress={() => this.props.navigation.openDrawer()}
/>
</View>
),
})
},
},
);
this.props is only used in a react class. I assume you're using react-navigation v2 then you should dispatch DrawerAction like below
import React, { Component } from 'react';
import { createStackNavigator, NavigationActions } from 'react-navigation'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { DrawerActions } from 'react-navigation';
import { Draw } from './DrawNav.js'
export const RootStack = createStackNavigator (
{
DrawNav: {
screen: Draw,
navigationOptions: ({ navigation }) => ({
//Hide the shadow of the header
headerStyle: {
elevation:0,
shadowColor: 'transparent',
shadowRadius: 0,
shadowOffset: {
height: 0,
}
},
headerLeft: (
<View style={{marginLeft: 10}}>
<Icon
name="menu"
size={25}
color="#D4AF37"
onPress={() => navigation.dispatch(DrawerActions.openDrawer())}
/>
</View>
),
})
},
},
);

React Navigation Scroll View like transition?

I want to do something like:
Is this possible?
The default is like this:
Thanks.
I believe the two effects you are showing are the same. The only difference is that the desired one has navigation bar at the top which has an animation that looks like the bar is standing still while the text on it changed. It you add a navigation bar to your example you would see that they are the same.
Update
The following code achieve the visual effect. Note that I used a TabNavigator instead of a StackNavigator:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import { StackNavigator, TabNavigator } from 'react-navigation';
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
const InitialScreen = (props) =>
<View style={[styles.container, { backgroundColor: 'gray' }]}>
<TouchableOpacity onPress={() => props.navigation.navigate('Final')}>
<Text>Initial Screen</Text>
</TouchableOpacity>
</View>;
const FinalScreen = (props) =>
<View style={[styles.container, { backgroundColor: 'pink' }]}>
<TouchableOpacity onPress={() => props.navigation.navigate('Initial')}>
<Text>Final Screen</Text>
</TouchableOpacity>
</View>;
const App = TabNavigator({
Initial: { screen: InitialScreen },
Final: { screen: FinalScreen },
}, {
animationEnabled: true,
navigationOptions: {
tabBarVisible: false,
},
});
AppRegistry.registerComponent('testTransition', () => App);
Put it in your index.ios.js to try it out and play around with it :P

Resources