I updated my react native application to SDK 42. After that left navigator bar is not working. it only popup and show image only. but if i comment contentComponent: CustomDrawerContentComponent part in the createDrawerNavigator then image disapear and my navigation menus are showing.
My Code
const CustomDrawerContentComponent = (props) => (
<ScrollView>
<Container style={styles.container}>
<Header style={styles.drawerHeader}>
<Body style={styles.headerBody}>
<Image
ref={(ref) => this.logoImgRef = ref}
style={{ width: 120, height: 120, marginTop:10}}
source={imgLogo}
/>
</Body>
</Header>
<Content>
<DrawerItems {...props}/>
</Content>
</Container>
</ScrollView>
)
const DrMenu= createDrawerNavigator({
"Home": {
navigationOptions: {
drawerIcon: () => (
<Icon name='home'
color='#1976D2' size={26}/>
),
title: i18n.t('home'),
},
screen: (props) => <FLHome {...props} propName={FLHome} {...contactData} />
},
"Logout": {
navigationOptions: {
drawerIcon: () => (
<Icon name='sign-out'
color='#1976D2' size={26}/>
),
title: i18n.t('logout'),
},
screen: (props) => <Logout {...props} propName={Logout} />
},
}, {
initialRouteName: "Home",
drawerPosition: 'left',
contentComponent: CustomDrawerContentComponent,
contentOptions: {
activeTintColor: '#1976D2',
inactiveTintColor :'#1999CE',
activeBackgroundColor :'#E8EAF6',
},
drawerOpenRoute: 'DrawerOpen',
drawerCloseRoute: 'DrawerClose',
}
);
const App = createAppContainer(DrMenu);
return(
<App/>
);
}
react-native provides functional creation of rendering objects
const DateSelect = ()=>{
return (<DataSelect/>)
}
export default DateSelect
//import alias
import DateSelection from 'path';
//use
render.dom
<DateSelection/>
I found a solution for this problem. That is you have to create another JS page and render in this page like this below,
export default CustomDrawerContentComponent = props => (
<ScrollView>
<View style={styles.container}>
<Image
source={imgLogo}
style={{ width: 120, height: 120, marginTop:10}}
/>
</View>
<View>
<DrawerNavigatorItems {...props}/>
</View>
</ScrollView>
);
Then you can render in this way in the DrawerViewConfig
contentComponent: props => <CustomDrawerContentComponent {...props} />
Related
StackOverflow I am very new to react native since I implement drawer navigation now I want to include a logout button at the end of the drawer but I don't find how to do that any good practice and ideas about how to achieve this kind of functionality. this is my code for drawer I find it from hours of google and it works fine but it has functions of screens I don't find any option of how to make a logout link in this code if this code is not correct then suggest any other good snippet thanks in advance
import React from 'react';
import { Ionicons } from '#expo/vector-icons'
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { createDrawerNavigator, createStackNavigator, createAppContainer } from 'react-navigation';
import { DrawerActions } from 'react-navigation-drawer';
// _signOutAsync = async () => {
// await AsyncStorage.clear();
// this.props.navigation.navigate('Auth');
// };
const HomeScreen = () => (
<View style={styles.container}>
<Text>Home Screen!</Text>
</View>
);
const ProfileScreen = () => (
<View style={styles.container}>
<Text>Profile Screen!</Text>
</View>
);
const SettingsScreen = () => (
<View style={styles.container}>
<Text>Settings Screen!</Text>
</View>
);
const DrawerNavigator = createDrawerNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => ({
title: 'Home Screen',
drawerLabel: 'Home',
drawerIcon: () => (
<Ionicons name="ios-home" size={20} />
)
})
},
Profile: {
screen: ProfileScreen,
navigationOptions: ({ navigation }) => ({
title: 'Profile Screen',
drawerLabel: 'Profile',
drawerIcon: () => (
<Ionicons name="ios-person" size={20} />
)
})
},
Settings: {
screen: SettingsScreen,
navigationOptions: ({ navigation }) => ({
drawerIcon: () => (
<Ionicons name="ios-settings" size={20} />
)
})
},
});
const StackNavigator = createStackNavigator({
DrawerNavigator: {
screen: DrawerNavigator,
navigationOptions: ({ navigation }) => {
const { state } = navigation;
if(state.isDrawerOpen) {
return {
headerLeft: ({titleStyle}) => (
<TouchableOpacity onPress={() => {navigation.dispatch(DrawerActions.toggleDrawer())}}>
<Ionicons name="ios-close" style={styles.menuClose} size={36} color={titleStyle} />
</TouchableOpacity>
),
}
}
else {
return {
headerLeft: ({titleStyle}) => (
<TouchableOpacity onPress={() => {navigation.dispatch(DrawerActions.toggleDrawer())}}>
<Ionicons name="ios-menu" style={styles.menuOpen} size={32} color={titleStyle} />
</TouchableOpacity>
),
}
}
}
}
})
export default createAppContainer(StackNavigator);
You can create one content component to render inside your Drawer Navigator, making it easier to modify.
I will explain with your example (I am assuming that it is your App.js file):
//import CustomDrawer from '...'
const DrawerNavigator = createDrawerNavigator({
Home: {
screen: HomeScreen,
navigationOptions: ({ navigation }) => ({
title: 'Home Screen',
drawerLabel: 'Home',
drawerIcon: () => (
<Ionicons name="ios-home" size={20} />
)
})
},
Profile: {
screen: ProfileScreen,
navigationOptions: ({ navigation }) => ({
title: 'Profile Screen',
drawerLabel: 'Profile',
drawerIcon: () => (
<Ionicons name="ios-person" size={20} />
)
})
},
Settings: {
screen: SettingsScreen,
navigationOptions: ({ navigation }) => ({
drawerIcon: () => (
<Ionicons name="ios-settings" size={20} />
)
})
},
//Here you will add one more pair of curly brackets to add more configs.
}, {
initialRouteName: 'Home',
contentComponent: CustomDrawer //This is the option that will allow you to add the button
});
You will create one entire component to modify like you want and then render inside the Drawer Navigator. Remember, I am using CustomDrawer name, you will import this component inside your App.js file.
import React from 'react';
import { View, Text, Image, StyleSheet } from 'react-native';
import { Button } from 'react-native-elements';
import { DrawerNavigatorItems } from 'react-navigation-drawer';
const CustomDrawer = ({ ...props }) => {
return (
<>
<View>
<DrawerNavigatorItems
{...props}
itemsContainerStyle={{}}
itemStyle={{}}
/>
</View>
<View
style={{
flexDirection: 'row',
alignSelf: 'center',
position: 'relative',
marginBottom: 20,
}}
>
<Button
title={'Log out'}
buttonStyle={{ width: 200, borderRadius: 20 }}
onPress={}
/>
</View>
</>
);
};
const styles = StyleSheet.create({});
export default CustomDrawer;
Here I am rendering only the CustomDrawer props, that is the itens that you create in your App.js and rendering it (specifically it is the ...props that I am passing in DrawerNavigationItems, so you can customize it like you want, like one normal screen, place buttons, create views and apply styles to it.
You can also instead of creating one new screen to render inside your Drawer Navigator code it inside your App.js, but personally I feel it much messed up
You can learn more with this tutorial
I want to hide one of my tabs conditionally if user login,
So I have 5 Tabs If user login\register I get a boolean from a redux store,
if this user login i want to how a "Library tab" if not login, i don't want to show this tab "Library" with others and just keep 4 tabs in the App
Code
import {createAppContainer} from 'react-navigation';
import {createBottomTabNavigator} from 'react-navigation-tabs';
let {isLogin} = store.getState().user;
const TabHome = createBottomTabNavigator(
{
Home: {
screen: Home,
navigationOptions: {
tabBarLabel: 'Home',
},
},
Browse: {
screen: Browse,
navigationOptions: {
tabBarLabel: 'Browse',
},
},
Search: {
screen: Search,
navigationOptions: {
tabBarLabel: 'Search',
headerShown: false,
},
},
Radio: {
screen: Radio,
navigationOptions: {
tabBarLabel: 'Radio',
},
},
Library: isLogin ? (
{
screen: YourLibrary,
navigationOptions: {
tabBarLabel: 'Library',
},
}
) : (
<View /> // Or :null => Not work and got the under error msg
),
// Library: {
// screen: YourLibrary,
// },
},
)
export default createAppContainer(TabHome);
Error: The component for route 'Library' must be a React component.
For example:
import MyScreen from './MyScreen'; ... Library: MyScreen, }
You can also use a navigator:
import MyNavigator from './MyNavigator'; ... Library: MyNavigator, }
In React Navigation v5:
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
function HomeScreen(props) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
function AboutScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>About!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
function MyTabs() {
const [showTab, setShowTab] = React.useState(true);
// Show the about tab after 5 seconds.
// Change this to use Redux or however
// you would like to change which tabs are displayed
setTimeout(() => {
setShowTab(false);
console.log('Hide tab');
}, 5000);
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
{showTab ? (
<Tab.Screen
name="About"
component={AboutScreen}
options={{
tabBarLabel: 'About',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="book" color={color} size={size} />
),
}}
/>
) : null}
<Tab.Screen
name="Settings"
component={SettingsScreen}
options={{
tabBarLabel: 'Settings',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="settings" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<MyTabs />
</NavigationContainer>
);
}
Example in Expo https://snack.expo.io/#jackvial/createbottomtabnavigator-%7C-react-navigation-v5
You'd know that you can override the Tabbar Component and add your own logic for it?
Maybe this gives you an Idea about that: https://stackoverflow.com/a/58520533/1256697
Maybe this way, you can set conditional styles to show or hide single items of your TabBar.
remove Library tab definition from TabHome and add it just before exporting the component:
if(isLogin) {
TabHome.Library = {
screen: YourLibrary,
navigationOptions: {
tabBarLabel: 'Library',
}
}
}
export default createAppContainer(TabHome)
I am using createDrawerNavigator and inside this I made a custom profile view. When I press navigate I want to move to another screen.
But this give me an error undefined is not an object (evaluating"_this.props.navigation"). Other components one, two, three works fine.
This is my code:
export default class App extends Component {
render() {
return (
<View style={{flex:1, marginTop:30}}>
<AppContainer/>
</View>
);
}
}
const CustomDrawerContentComponent = (props)=> {
return(
<SafeAreaView style={{flex:1}}>
<View style={{ height:100, backgroundColor: '#9FA8DA' }}>
<Image
style={{marginLeft:20,height:100,width:100,borderRadius:50}}
source={require('./assets/puppy.jpg')}/>
</View>
<View style={{flexDirection:'row', margin:20, alignItems:'center'}}>
//////here is where I get an error
<TouchableOpacity
style={{marginTop:0}}
onPress={()=> {this.props.navigation.navigate('profile')}}>
<Text style={{fontSize:18, fontWeight:'bold'}}>navigate</Text>
<Image
style={{height:12,width:12}}
source={require('./assets/drawable-hdpi/ic_arrow_depth.png')}/>
</TouchableOpacity>
</View>
<ScrollView>
<DrawerItems {...props}/>
</ScrollView>
</SafeAreaView>
)
}
const AppDrawerNavigator = createDrawerNavigator({
one: AppStackNavigator,
two: BoardScreen,
three: NotificationScreen,
},{
contentComponent:CustomDrawerContentComponent,
})
const AppStackNavigator = createStackNavigator({
profile: {
screen: profileScreen,
navigationOptions: {
header: null
},
},
})
const StartSwitchNavigator = createSwitchNavigator(
{
App: AppDrawerNavigator,
},
{
initialRouteName: 'App',
}
)
Your CustomDrawerContentComponent component is functional component. Use props.navigation directly instead of this.props
I'm trying to hide a header in a BottomTabNavigator but this one came from a StackNavigator. I already tried to use the header: null inside the page and other ways but nothing works!
const AppTabNav = createBottomTabNavigator({
HomeScr:{
screen:Home,navigationOptions:{tabBarLabel:'Inicio',tabBarIcon: ({tintColor}) => (<Icon name='home' color={tintColor} size={25}/>)}
},
Settings:{
screen:Config,navigationOptions:{ tabBarLabel:'Configurações',tabBarIcon:({ tintColor })=>(<Icon name="settings" color={tintColor} size={25}/>)}
}
})
const AppStackNavigator = createStackNavigator({
AppTab:{
screen:AppTabNav,
navigationOptions:({navigation}) =>({
title:'Bem vindo #USER',
headerLeft:(
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<View style={{paddingHorizontal:10}}>
<Icon name="menu" color='black' size={24}/>
</View>
</TouchableOpacity>)
})
}
},{tabBarOptions:{
activeTintColor:'blue',
inactiveTintColor:'black'
}})
This is the header I want to hide when I click on configurações in the Bottombar
Imagem
This is the code of the Config.js file
export default class Config extends Component {
static navigationOptions = {
header: null,
drawerIcon: ({ tintColor }) => ( <Icon name='settings' style={{color:tintColor ,fontSize:24}} />)
}
SignOut = async() => {
AsyncStorage.clear()
this.props.navigation.navigate('AuthLoading')
}
render() {
return (
<Container>
<Header>
<Left style={{flex:1}}>
<Icon name="menu" color='black' size={24} onPress={() => this.props.navigation.openDrawer()}/>
</Left>
<Body style={{flex: 1,justifyContent: 'center'}}>
<Title>Configurações</Title>
</Body>
<Right style={{flex:1}}/>
</Header>
<View style={{flex :1, alignItems:'center', justifyContent:'center'}}>
<Text>Configurações</Text>
</View>
</Container>
);
}
}
Just add this into your component code and Header will be hidden
tabBarVisible: false
export default class Config extends Component {
static navigationOptions = {
tabBarVisible: false,
drawerIcon: ({ tintColor }) => ( <Icon name='settings' style={{color:tintColor ,fontSize:24}} />)
}
SignOut = async() => {
AsyncStorage.clear()
this.props.navigation.navigate('AuthLoading')
}
render() {
return (
<Container>
<Header>
<Left style={{flex:1}}>
<Icon name="menu" color='black' size={24} onPress={() => this.props.navigation.openDrawer()}/>
</Left>
<Body style={{flex: 1,justifyContent: 'center'}}>
<Title>Configurações</Title>
</Body>
<Right style={{flex:1}}/>
</Header>
<View style={{flex :1, alignItems:'center', justifyContent:'center'}}>
<Text>Configurações</Text>
</View>
</Container>
);
}
}
I'm using "react-navigation": "^2.11.2" and have a TabNavigator() with 3 tabs: A, B and C.
So I use:
...
_Profile: {
screen: TabNavigator(
{
First: A,
Second: B,
Third: C
},
{
tabBarPosition: "top",
swipeEnabled: true,
lazy: false
}
),
navigationOptions: ({ navigation }) => ({
header: <ProfileHeader navigation={navigation} />
})
},
...
I want to have a fixed footer in Pages A and B but NOT in C.
First I tried to create a footer in each A and B but the result is something different from what I want, See images below:
But when I try to swipe to tab B, You can see the footer is NOT FIXED:
Any idea about this?
Thanks in advance!
I asked the contributors and we have a full example from now on:
Custom Tabs with footer:
Github example
UPDATE
I guess the link is broken so I paste the code here:
import React from "react";
import {
LayoutAnimation,
View,
StyleSheet,
StatusBar,
Text
} from "react-native";
import { SafeAreaView, createMaterialTopTabNavigator } from "react-navigation";
import Ionicons from "react-native-vector-icons/Ionicons";
import { Button } from "./commonComponents/ButtonWithMargin";
class MyHomeScreen extends React.Component {
static navigationOptions = {
tabBarLabel: "Home",
tabBarIcon: ({ tintColor, focused, horizontal }) => (
<Ionicons
name={focused ? "ios-home" : "ios-home"}
size={horizontal ? 20 : 26}
style={{ color: tintColor }}
/>
)
};
render() {
const { navigation } = this.props;
return (
<SafeAreaView forceInset={{ horizontal: "always", top: "always" }}>
<Text>Home Screen</Text>
<Button
onPress={() => navigation.navigate("Home")}
title="Go to home tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</SafeAreaView>
);
}
}
class RecommendedScreen extends React.Component {
static navigationOptions = {
tabBarLabel: "Recommended",
tabBarIcon: ({ tintColor, focused, horizontal }) => (
<Ionicons
name={focused ? "ios-people" : "ios-people"}
size={horizontal ? 20 : 26}
style={{ color: tintColor }}
/>
)
};
render() {
const { navigation } = this.props;
return (
<SafeAreaView forceInset={{ horizontal: "always", top: "always" }}>
<Text>Recommended Screen</Text>
<Button
onPress={() => navigation.navigate("Home")}
title="Go to home tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</SafeAreaView>
);
}
}
class FeaturedScreen extends React.Component {
static navigationOptions = ({ navigation }) => ({
tabBarLabel: "Featured",
tabBarIcon: ({ tintColor, focused, horizontal }) => (
<Ionicons
name={focused ? "ios-star" : "ios-star"}
size={horizontal ? 20 : 26}
style={{ color: tintColor }}
/>
)
});
render() {
const { navigation } = this.props;
return (
<SafeAreaView forceInset={{ horizontal: "always", top: "always" }}>
<Text>Featured Screen</Text>
<Button
onPress={() => navigation.navigate("Home")}
title="Go to home tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</SafeAreaView>
);
}
}
const SimpleTabs = createMaterialTopTabNavigator({
Home: MyHomeScreen,
Recommended: RecommendedScreen,
Featured: FeaturedScreen
});
class TabNavigator extends React.Component {
static router = SimpleTabs.router;
componentWillUpdate() {
LayoutAnimation.easeInEaseOut();
}
render() {
const { navigation } = this.props;
const { routes, index } = navigation.state;
const activeRoute = routes[index];
let bottom = null;
if (activeRoute.routeName !== "Home") {
bottom = (
<View style={{ height: 50, borderTopWidth: StyleSheet.hairlineWidth }}>
<Button title="Check out" onPress={() => {}} />
</View>
);
}
return (
<View style={{ flex: 1 }}>
<StatusBar barStyle="default" />
<SafeAreaView
style={{ flex: 1 }}
forceInset={{ horizontal: "always", top: "always" }}
>
<SimpleTabs navigation={navigation} />
</SafeAreaView>
{bottom}
</View>
);
}
}
export default TabNavigator;