Render header right button conditionally with React Navigation in React Native - javascript

I am trying to conditionally render the Entypo new-message icon in the right header based on a boolean variable (if the variable is true, then the icon will show up in the header). Please see the minimum reproducible code below. Thanks in advance.
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { Ionicons, MaterialCommunityIcons, Entypo } from "#expo/vector-icons";
const Tab = createBottomTabNavigator();
const MainTabNavigator = () => {
return (
<Tab.Navigator
initialRouteName="Chats"
screenOptions={{
tabBarStyle: { backgroundColor: "whitesmoke" },
headerStyle: { backgroundColor: "whitesmoke" },
}}
>
<Tab.Screen
name="Chats"
component={ChatsScreen}
options={({ navigation }) => ({
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons
name="message-processing-outline"
size={size}
color={color}
/>
),
headerRight: () => (
<Entypo
onPress={() => navigation.navigate("Contacts")}
name="new-message"
size={18}
color={"royalblue"}
style={{ marginRight: 15 }}
/>
),
})}
/>
</Tab.Navigator>
);
};
export default MainTabNavigator;

You can do it as below, with a Conditional (ternary) operator. Just replace boleanVariable with your actual variable.
options={({ navigation }) => ({
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="message-processing-outline" size={size} color={color} />
),
headerRight: () =>
!boleanVariable ? (
<></>
) : (
<Entypo
onPress={() => navigation.navigate("Contacts")}
name="new-message"
size={18}
color={"royalblue"}
style={{ marginRight: 15 }}
/>
),
})}

Related

Calling a function from React navigation header (getParam is not a function)

I have this icon that needs to run a function onLogout in a separate file
First I tried passing navigation param to bottomTab options like so
<BottomTab.Screen
name="Settings"
component={Settings}
options={(navigation) => ({
title: "Settings",
tabBarIcon: () => <Icon name="settings" size={20} color="black" />,
headerRight: (
<Icon
onPress={navigation.getParam('onLogout')}
style={{ marginRight: 14 }} name="log-out" size={18} color="black" />
)
})}
/>
In the settings screen where the function lives I have initialized the function like so
this.props.navigation.setParams({ onLogout: this.onLogout });
I have tried inside componentDidMount and componentWillMount
Also tried to bind it
constructor(props) {
super(props);
this.onLogout = this.onLogout.bind(this);
}
TypeError: navigation.getParam is not a function. (In
'navigation.getParam('onLogout')', 'navigation.getParam' is undefined)
At one point the function get executed but without me touching the icon but I changed to this
this.props.navigation.setParams({ onLogout: this.onLogout() });
Since that didn't work I tried writing the options in the file itself
export default class Settings extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
headerRight: (
<Icon
// onPress={navigation.getParam('onLogout')}
style={{ marginRight: 14 }} name="log-out" size={18} color="black" />
)
};
};
...
No icon shows up on the screen and nothing works with that method (title, ect...)
Try this :
<BottomTab.Screen
name="Settings"
component={Settings}
options={(props) => ({
title: "Settings",
tabBarIcon: () => <Icon name="settings" size={20} color="black" />,
headerRight:() =>(
<Icon
onPress={()=>props.route.params.onLogout()}
style={{ marginRight: 14 }} name="log-out" size={18} color="black" />
)
})}
/>

How to remove the Header from my App? Why is the Header displayed?

How to remove the Header from my App? Why is the Header displayed?
I want to remove the title from the Header, since each page has its own title, and that title takes up space from the screens.
I do not understand why it is displayed. I'm following a tutorial and as many times as I go through, I don't see a way to remove this.
I have followed the official documentation, but I cannot get rid of this nonsensical Header.
The navigation is handled from the AppStack.js file and the Header titles displayed are handled from the <Tab.Navigator> <Tab.Screen /> </Tab.Navigator>, but this is really the bottom tabs, and however, they are also displayed in the Header.
I show some image of what I cannot remove
How do I remove this Header which is unnecessary?
I have the correct dependencies:
"react": "17.0.2",
"react-native": "0.66.1",
"react-native-gesture-handler": "^ 1.10.3",
"react-native-onboarding-swiper": "^ 1.1.4",
"react-native-reanimated": "^ 2.2.3",
"react-native-safe-area-context": "^ 3.3.2",
"react-native-screens": "^ 3.8.0",
"react-native-vector-icons": "^ 8.1.0",
"react-native-webview": "^ 11.14.1",
"styled-components": "^ 5.3.3"
AppStack.js
import React from 'react'
import { View, TouchableOpacity, Text } from 'react-native'
import { createStackNavigator } from '#react-navigation/stack'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import Ionicons from 'react-native-vector-icons/Ionicons'
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5'
import HomeScreen from '../screens/HomeSreen'
import ChatScreen from '../screens/ChatScreen'
import ProfileScreen from '../screens/ProfileScreen'
import AddPostScreen from '../screens/AddPostScreen'
const Stack = createStackNavigator()
const Tab = createBottomTabNavigator()
const FeedStack = ({ navigation }) => (
<Stack.Navigator>
<Stack.Screen
name="Social React Native"
component={HomeScreen}
options={{
headerTitleAlign: 'center',
headerTitleStyle: {
color: '#2e64e5',
fontFamily: 'Kufam-SemiBoldItalic',
fontSize: 18,
},
headerStyle: {
shadowColor: '#fff',
elevation: 0,
},
headerRight: () => (
<View style={{ marginRight: 10 }}>
<FontAwesome5.Button
name="plus"
size={22}
backgroundColor="#fff"
color="#2e64e5"
onPress={() => navigation.navigate('AddPost')}
/>
</View>
),
}}
/>
<Stack.Screen
name="AddPost"
component={AddPostScreen}
options={{
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#2e64e515',
shadowColor: '#2e64e515',
elevation: 0,
},
headerBackTitleVisible: false,
headerBackImage: () => (
<View style={{ marginLeft: 15 }}>
<Ionicons name="arrow-back" size={25} color="#2e64e5" />
</View>
),
}}
/>
<Stack.Screen
name="HomeProfile"
component={ProfileScreen}
options={{
headerTitleAlign: 'center',
headerStyle: {
backgroundColor: '#fff',
shadowColor: '#fff',
elevation: 0,
},
headerBackTitleVisible: false,
headerBackImage: () => (
<View style={{ marginLeft: 15 }}>
<Ionicons name="arrow-back" size={25} color="#2e64e5" />
</View>
),
}}
/>
</Stack.Navigator>
)
const ProfileStack = ({ navigation }) => (
<Stack.Navigator>
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
)
const AppStack = () => {
const getTabBarVisibility = (route) => {
const routeName = route.state
? route.state.routes[route.state.index].name
: '';
if (routeName === 'Chat') {
return false;
}
return true;
}
return (
<Tab.Navigator
screenOptions={{
activeTintColor: '#2e64e5'
}}>
<Tab.Screen
name="Home"
component={FeedStack}
options={({ route }) => ({
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons
name="home-outline"
color={color}
size={size}
/>
),
})}
/>
<Tab.Screen
name="Messages"
component={ChatScreen}
options={({ route }) => ({
tabBarVisible: getTabBarVisibility(route),
tabBarIcon: ({ color, size }) => (
<Ionicons
name="chatbox-ellipses-outline"
color={color}
size={size}
/>
),
})}
/>
<Tab.Screen
name="Profile"
component={ProfileStack}
options={{
// tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<Ionicons name="person-outline" color={color} size={size} />
),
}}
/>
</Tab.Navigator>
)
}
export default AppStack
IMAGES:
you can add options={{ headerShown: false }}
<Tab.Screen
name="Messages"
component={ChatScreen}
options={({ route }) => ({
headerShown: false,
tabBarVisible: getTabBarVisibility(route),
tabBarIcon: ({ color, size }) => (
<Ionicons
name="chatbox-ellipses-outline"
color={color}
size={size}
/>
),
})}
/>

contentComponent: CustomDrawerContentComponent is not working after update to sdk 42

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} />

How to define custom header inside screen in react navigation 5?

i know we use options prop when we define screen in root file
<Stack.Screen
name="index"
component={Index}
options={({ navigation, route }) => ({
headerRight: (props) => (
<MaterialIcons name="add" size={30} style={{ marginRight: 20 }} />
),
})}
/>
But i want to define in the screen by itself like we used to do in react navigation 4
Index.navigationOptions = () => {
return {
headerRight: (
<MaterialIcons name="add" size={30} style={{ marginRight: 20 }} />
),
};
};
but how i can do it in react navigation 5?
use navigation.setOptions
function HomeScreen({ navigation }) {
React.useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<MaterialIcons name="add" size={30} style={{ marginRight: 20 }} />
),
});
}, [navigation]);

React Native fixed Footer with React Navigation

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;

Categories