I'm struggling with a navigation problem in React Navigation 5.x I have the following project structure, where (1) is a Stack Navigator, (2, 3 and 4) are different stacks nested in (1).
What I want to achieve: I want (1) header buttons to: go back a screen and go back to home.
(1):
<NavigationContainer>
<Stack.Navigator screenOptions={{cardStyleInterpolator: CardStyleInterpolators.forVerticalIOS, gestureDirection: 'vertical'}} >
<Stack.Screen
name='Home'
component={Pages.Home}
options={({navigation}: any) => ({
headerLeft: () =>
<TouchableOpacity onPress={() => navigation.navigate('Menu')}>
<Icon name='menu' size={Mixins.scaleHeight(25)} color={Colors.WHITE} style={{marginLeft: 20}}/>
</TouchableOpacity>,
headerRight: props => <Icon name='bell' size={Mixins.scaleHeight(20)} color={Colors.WHITE} style={{marginRight: 20}}/>,
headerTitle: '',
headerStyle: [{elevation: 0, borderWidth: 0, shadowOpacity: 0, borderColor: Colors.TRANSPARENT, backgroundColor: Colors.PRIMARY}],
cardStyleInterpolator: CardStyleInterpolators.forVerticalIOS,
})}
/>
<Stack.Screen
name='Menu'
component={Pages.Menu}
options={({navigation}: any) => ({
headerStyle: [{elevation: 0, borderWidth: 0, shadowOpacity: 0, borderColor: Colors.TRANSPARENT, backgroundColor: Colors.PRIMARY}],
headerRight: () =>
<TouchableOpacity onPress={() => navigation.popToTop()}>
<Icon name='close' size={Mixins.scaleHeight(25)} color={Colors.WHITE} style={{marginRight: 20}}/>
</TouchableOpacity>,
headerTitle: '',
headerLeft: () => <></>,
})}
/>
<Stack.Screen
name='Stack2'
component={Stack2}
options={({route, navigation}: any) =>( {
headerStyle: [{elevation: 0, borderWidth: 0, shadowOpacity: 0, borderColor: Colors.TRANSPARENT, backgroundColor: Colors.PRIMARY}],
headerBackTitle: ' ',
headerTitle: '',
headerBackTitleStyle: {color: '#fff'},
headerLeft: () =>
<TouchableOpacity onPress={() => navigation.goBack()}>
<HeaderBackImage textRegular='Stack' textBold='2'/>
</TouchableOpacity>,
headerRight: props =>
<TouchableOpacity onPress={() => navigation.popToTop()}>
<Icon name='close' size={Mixins.scaleHeight(24)} color={Colors.WHITE} style={{marginRight: 20}}/>
</TouchableOpacity>,
})}
/>
<Stack.Screen
name='Stack3'
component={Stack3}
options={({route, navigation}: any) =>( {
headerStyle: [{elevation: 0, borderWidth: 0, shadowOpacity: 0, borderColor: Colors.TRANSPARENT, backgroundColor: Colors.PRIMARY}],
headerBackTitle: ' ',
headerTitle: '',
headerBackTitleStyle: {color: '#fff'},
headerLeft: () =>
<TouchableOpacity onPress={() => navigation.goBack()}>
<HeaderBackImage textRegular='Stack' textBold='3'/>
</TouchableOpacity>,
headerRight: props =>
<TouchableOpacity onPress={() => navigation.popToTop()}>
<Icon name='close' size={Mixins.scaleHeight(24)} color={Colors.WHITE} style={{marginRight: 20}}/>
</TouchableOpacity>,
})}
/>
<Stack.Screen
name='Stack4'
component={Stack4}
options={({route, navigation}: any) =>( {
headerStyle: [{elevation: 0, borderWidth: 0, shadowOpacity: 0, borderColor: Colors.TRANSPARENT, backgroundColor: Colors.PRIMARY}],
headerBackTitle: ' ',
headerTitle: '',
headerBackTitleStyle: {color: '#fff'},
headerLeft: () =>
<TouchableOpacity onPress={() => navigation.goBack()}>
<HeaderBackImage textRegular='Stack' textBold='4'/>
</TouchableOpacity>,
headerRight: props =>
<TouchableOpacity onPress={() => navigation.popToTop()}>
<Icon name='close' size={Mixins.scaleHeight(24)} color={Colors.WHITE} style={{marginRight: 20}}/>
</TouchableOpacity>,
})}
/>
</Stack.Navigator>
</NavigationContainer>
(2):
const Stack2 = () => (
<Stack.Navigator screenOptions={{gestureDirection: 'horizontal'}}>
<Stack.Screen
name='ScreenA'
component={Pages.ScreenA}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name='ScreenB'
component={Pages.ScreenB}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name='ScreenC'
component={Pages.ScreenC}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name='ScreenD'
component={Pages.ScreenD}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>);
Problem: The (1) header navigation.goBack() won't go back a single screen on (2, 3 or 4) stack, it's going back from (2, 3 or 4) to (1) directly.
Is there a way to access (2, 3 or 4) navigation props from (1) header?
Try putting the back buttons in the screens of stacks 2,3,4.
Related
I have "ProfileScreen" declared in the App.js
function App({ navigation }) {
return (
<>
<StatusBar hidden />
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen
...
component={HomeScreen}
...
/>
<Stack.Screen
...
component={FeedScreen}
...
/>
<Stack.Screen
...
component={ProfileScreen}
...
/>
</Stack.Navigator>
</NavigationContainer>
</>
);
}
I access ProfileScreen inside FeedScreen.js
export const ProfileScreen = () => {
return(
<Text style={{ textAlign: "left", color: "black", fontSize: 24, fontFamily: 'Montserrat_100Thin_Italic' }}>
Hello
</Text>
);
}
Inside FeedScreen.js I want to navigate to ProfileScreen:
const Item = ({ item }, { navigation }) => {
return (
<>
<TouchableOpacity onPress={() => navigation.navigate("ProfileScreen")}>
<Text style={{ textAlign: "left", color: "white", fontSize: 24, fontFamily: 'Montserrat_100Thin_Italic' }}>
<Image
style={{ alignSelf: "center", borderRadius: 50 }}
source={{ uri: item.profile_picture, width: 48, height: 48 }}
/>
{item.username}
</Text>
</TouchableOpacity>
</>
);
};
Unfortunately, everything returns Undefined is not an object (evaluating 'navigation.navigate')
For an easy solution use the hook useNavigation inside your Item component as a following:
import { useNavigation } from '#react-navigation/native';
const Item = ({item}) => {
const navigation = useNavigation();
return (
<TouchableOpacity onPress={() => navigation.navigate('ProfileScreen')}>
<Text
style={{
textAlign: 'left',
color: 'white',
fontSize: 24,
fontFamily: 'Montserrat_100Thin_Italic',
}}>
<Image
style={{alignSelf: 'center', borderRadius: 50}}
source={{uri: item.profile_picture, width: 48, height: 48}}
/>
{item.username}
</Text>
</TouchableOpacity>
);
};
Your syntax was wrong for using navigation prop inside FeedScreen
It should be like this
const Item = ({ item , navigation }) => {
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}
/>
),
})}
/>
I'm making reactive Navigator by using react-native expo
I want to make a code like this
if isLoggedin is false show <LoginContent props={props} />
if isLoggedin is true show <Text>user</Text>
When I did console.log(isLoggedin) the result was undefined
And My code doesn't work even if I change the isLoggedIn value.
This is App.js
import * as React from 'react';...
const Drawer = createDrawerNavigator();
function DrawerNavigate() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
// const changeCheck = () => {
// setIsLoggedIn((isLoggedIn) => !isLoggedIn);
// };
return (
<Drawer.Navigator
screenOptions={{ headerShown: false, headerStyle: { backgroundColor: 'transparent', elevation: 0, shadowOpacity: 0, shadowColor: 'transparent' } }}
drawerContent={(props) => <DrawerContent isLoggedIn={isLoggedIn} changeCheck={changeCheck} {...props} />}
>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Note" component={Note} />
<Drawer.Screen name="CheckedList" component={CheckedList} />
<Drawer.Screen name="UncheckedList" component={UncheckedList} />
<Drawer.Screen name="Support" component={Support} />
<Drawer.Screen name="Setting" component={Setting} />
<Drawer.Screen name="Login" component={Login} />
</Drawer.Navigator>
);
}
function Sidebar() {
return (
<>
<NavigationContainer>
<DrawerNavigate />
</NavigationContainer>
</>
);
}
export default function App() {
return (
<>
<Sidebar style={{ width: 100 }} />
</>
);
}
and this is the part of DrawerContect.js
import * as React from 'react';...
export function DrawerContent(props, { isLoggedIn, changeCheck }) {
const press = () => {
console.log(isLogginedIn);
};
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
<View style={{ alignItems: 'center', alignContent: 'center' }}>
<View style={{ marginHorizontal: 20, flexDirection: 'column', marginVertical: 20 }}>
<View>{isLoggedIn ? <LoginContent props={props} /> : <Text style={Styles.title}>User</Text>}</View>
</View>
</View>
.
.
.
Whatever variables you have passed in DrawerContent will be accessible in first argument. So you need to destructure first argument which is props to get isLoggedIn.
export function DrawerContent(props) {
const { isLoggedIn, changeCheck } = props; // change this
const press = () => {
console.log(isLogginedIn);
};
return (
<View style={{ flex: 1 }}>
<DrawerContentScrollView {...props}>
<View style={{ alignItems: 'center', alignContent: 'center' }}>
<View style={{ marginHorizontal: 20, flexDirection: 'column', marginVertical: 20 }}>
<View>{isLoggedIn ? <LoginContent props={props} /> : <Text style={Styles.title}>User</Text>}</View>
</View>
</View>
I added a couple of header right buttons, but when I click them, I get the following error:
TypeError: undefined is not an object (evaluating '_this.props.navigation.navigate')
This is the code for the header, and it has the header right buttons:
<Stack.Screen
name="Tabs"
component={Tabs}
options = {{
title: " ",
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 24,
color: '#FFFFFF'
},
headerStyle: {
backgroundColor: '#121212',
shadowColor: 'transparent'
},
headerRight: () => (
<View style={{flexDirection: "row"}}>
<TouchableOpacity
style={{paddingRight: 20}}
onPress={() => this.props.navigation.navigate('Search')}>
<Ionicons name="ios-search" size={25} color="white" />
</TouchableOpacity>
<TouchableOpacity
style={{paddingRight: 20}}
onPress={() => this.props.navigation.navigate('Notifications')}>
<Ionicons name="md-notifications" size={25} color="white" />
</TouchableOpacity>
</View>
),
}}/>
How can I access navigation in the header?
EDIT: Followed the docs and changed it to this:
<Stack.Screen
name="Tabs"
component={Tabs}
options = {( navigation ) => ({
title: " ",
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 24,
color: '#FFFFFF'
},
headerStyle: {
backgroundColor: '#121212',
shadowColor: 'transparent'
},
headerRight: () => (
<View style={{flexDirection: "row"}}>
<TouchableOpacity
style={{paddingRight: 20}}
onPress={() => navigation.navigate('Search')}>
<Ionicons name="ios-search" size={25} color="white" />
</TouchableOpacity>
<TouchableOpacity
style={{paddingRight: 20}}
onPress={() => navigation.navigate('Notifications')}>
<Ionicons name="md-notifications" size={25} color="white" />
</TouchableOpacity>
</View>
),
})}/>
But now getting this error:
TypeError: navigation.navigate is not a function. (In 'navigation.navigate('Search')', 'navigation.navigate' is undefined)
How can I access navigation in the header?
You can define options as a function that takes the navigation object as an argument:
options={({ navigation }) => ({
title: " ",
headerTitleStyle: { ... }
})}
Here is a simplified working example.
Other use cases can be found in react-navigation documentation.
Hello guys I want to create stylish and custom bottom tab navigation in react native can anyone have any idea how to create this mention in above
const customTabBarStyle = {
activeTintColor: '#0091EA',
inactiveTintColor: 'gray',
style: {backgroundColor: 'white' },
}
return (
<Tab.Navigator
initialRouteName="Home"
activeColor="#fff"
tabBarOptions={customTabBarStyle}
shifting="false">
<Tab.Screen
name="Home"
options={{
tabBarLabel: '',
tabBarIcon: ({ color }) => (
<Icon name="home" color={color} size={26} />
)
}}
component={HomeScreen} />
<Tab.Screen
name="Workout"
options={{
tabBarLabel: '',
tabBarIcon: ({ color }) => (
<Icon name="fitness-center" color={color} size={26} />
)
}}
component={WorkoutTabScreen} />
<Tab.Screen
name="Add"
options={{
tabBarLabel: '',
tabBarIcon: ({ color }) => (
<View
style={{
position: 'absolute',
bottom: 0, // space from bottombar
height: 68,
width: 68,
borderRadius: 68,
justifyContent: 'center',
alignItems: 'center',
}}
>
<Icon name="add-circle-outline" color="grey" size={68}/>
</View>
)
}}
component={PayScreenComponent}/>
<Tab.Screen
name="Store"
options={{
tabBarLabel: '',
tabBarIcon: ({ color }) => (
<Icon name="store" color={color} size={26} />
)
}}
component={StoreLandingScreen} />
<Tab.Screen
name="Profile"
options={{
tabBarLabel: '',
tabBarIcon: ({ color }) => (
<Icon name="perm-identity" color={color} size={26} />
)
}}
component={ProfileScreen} />
</Tab.Navigator>
);
In React Navigation V5, there is a prop for Tab.Navigator component which you can pass whole custom bottom bar component
<Tab.Navigator tabBar={(props) => <CustomTabBar/>}>
<Tab.Screen .../>
</Tab.Navigator>
Nice explanation with good example to use custom tab bar using react-navigation
https://dev.to/hrastnik/lets-create-a-custom-animated-tab-bar-with-react-native-3496
Have a look on this great framework, React-Native-Tab-View.
https://github.com/react-native-community/react-native-tab-view
Just use tabBarPosition: bottom and render your Tabs as you'd like to.
import {createBottomTabNavigator,} from 'react-navigation'
const ACTIVE_TAB_COLOR = '#60C3FF'
const INACTIVE_TAB_COLOR = '#aaa'
const BottomStack = createBottomTabNavigator(
{
TAB_WALLET: {
screen:Screen1,
navigationOptions: {
tabBarLabel: 'Screen1',
tabBarIcon: ({ focused }) => <Icon name='iconname' focused={focused} color={focused ? ACTIVE_TAB_COLOR : INACTIVE_TAB_COLOR}/>
}
},
TAB_SEND: {
screen: Screen2,
navigationOptions: {
tabBarLabel: 'Screen2',
tabBarIcon: ({ focused }) => <Icon name='search' focused={focused} color={focused ? ACTIVE_TAB_COLOR : INACTIVE_TAB_COLOR} />
}
},
TAB_ACTIVITIES: {
screen: Screen3,
navigationOptions: {
tabBarLabel: 'Screen3'
tabBarIcon: ({ focused }) => <Icon name='paper' focused={focused} color={focused ? ACTIVE_TAB_COLOR : INACTIVE_TAB_COLOR}/>
}
}
},
{
tabBarPosition: 'bottom',
swipeEnabled: false,
animationEnabled: false,
tabBarOptions: {
activeTintColor: ACTIVE_TAB_COLOR,
inactiveTintColor: INACTIVE_TAB_COLOR,
showLabel: true,
style: {
borderTopWidth: 0,
paddingTop: 3,
paddingBottom: 4,
height: 60,
shadowColor: '#000',
shadowOpacity: 0.1,
shadowRadius: 20,
shadowOffset: { width: 0, height: 0 }
}
}
})