Using header buttons to navigate to another screen using react-navigaton - react-native

I have created a stack navigator with a header button which will be used to navigate to another screen, however I get this error when I try to goto another screen
TypeError: undefined is not an object (evaluating 'navigation.navigate')
And when I console.log(navigation) its undefined. But however when I create a button within a component & navigate to another screen it works. Its only the header buttons that are give me issues.
import {createStackNavigator} from '#react-navigation/stack';
import TabNav from './TabNavBar';
import TestingScreen from '../components/TestingScreen';
const Stack = createStackNavigator();
const NavTest = ({navigation}) => {
navigation.navigate('testingScreen');
};
const StackNavigatorContainer = () => {
return (
<Stack.Navigator>
<Stack.Screen
name={'tabNavigator'}
component={TabNav}
options={{
headerLeft: () => (
<Button title={'go to testing screen'} onPress={NavTest} />
),
}}
/>
<Stack.Screen name={'testingScreen'} component={PostInvoice} />
</Stack.Navigator>
);
};
export default StackNavigatorContainer;
I've also tried...
<Stack.Screen
name={'tabNavigator'}
component={TabNav}
options={{
headerLeft: ({navigation}) => (
<Button title={'go to testing screen'} onPress={() => navigation.navigate('testingScreen)} />
),
}}
/>
And
<Stack.Screen
name={'tabNavigator'}
component={TabNav}
options={{
headerLeft: () => (
<Button title={'go to testing screen'} onPress={({navigation}) => navigation.navigate('testingScreen)} />
),
}}
/>
``

To improve your understanding about my answer, I want to share my code that working well.
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const AppStack = createStackNavigator();
<NavigationContainer>
<AppStack.Navigator>
<AppStack.Screen name="Home" component={Home}
options={({ navigation }) => {
return {
headerTitleAlign: 'center',
headerMode: 'screen',
headerRight: () => (
<Button
onPress={() =>
navigation.navigate('Options')}
title="Crete Group"
color="#00f"
/>
),
}
}}
/>
<AppStack.Screen name="Options" component{Groupoptions} />
</AppStack.Navigator>
</NavigationContainer>
I hope this code help you surely.

Related

Expo Material Bottom Tabs Navigator doesn't work -> showing default BottomNavigation from React-Native-Paper

I've been trying to create a normal material bottom tabs navigator and it just doesnt want to work. I also tried another identical code I had and there it works like it should, but with this code the Material bottom Tabs Navigator shows the BottomNavigation from React-Native-Paper. Is there any help?Anything i have to change?
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import AuthScreen from './screens/AuthScreen';
import HomeScreen from './screens/HomeScreen';
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { userAuthStateListener } from './redux/actions/auth';
const Stack = createNativeStackNavigator()
export default function Main() {
const currenUserObject = useSelector(state => state.auth) // access data from redux from here
const dispatch = useDispatch()
useEffect(() => {
dispatch(userAuthStateListener());
}, []);
if (currenUserObject == null) {
console.log("nothing in user obj")
} else {
console.log("this prints" + { currenUserObject })
}
return (
<NavigationContainer>
<Stack.Navigator>
{currenUserObject.currentUser == null ?
<Stack.Screen name='AuthScreen' component={AuthScreen} options={{ headerShown: false }} />
:
<>
<Stack.Screen name='hb' component={HomeScreen} options={{ headerShown: false }} />
</>
}
</Stack.Navigator>
</NavigationContainer>
)
}
And the HomeScreen should have the material bottom tabs navigator.
import { View, Text, StyleSheet, SafeAreaView } from 'react-native'
import React from 'react'
import { Feather } from '#expo/vector-icons'
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
const Tab = createMaterialBottomTabNavigator();
const Test = () => {
return (
<View style={{backgroundColor:"blue"}}>
<Text>Test</Text>
</View>
)
}
//options={{ tabBarIcon: ({ color }) => (<Feather name="home" size={24} color={color} />)}}
//barStyle={{ backgroundColor: "black" }}
export default function HomeScreen() {
return (
<Tab.Navigator barStyle={{ backgroundColor: 'black' }} activeColor="white" shifting={true}>
<Tab.Screen name="Home" component={Test} />
<Tab.Screen name="Search" component={Test} options={{ tabBarColor:"white",tabBarBadge:false, tabBarIcon: ({ color }) => (<Feather name="search" size={24} color={color} />) }} />
<Tab.Screen name="Post" component={Test} options={{ tabBarIcon: ({ color }) => (<Feather name="plus-square" size={24} color={color} />) }} />
<Tab.Screen name="Chat" component={Test} options={{ tabBarIcon: ({ color }) => (<Feather name="message-square" size={24} color={color} />) }} />
<Tab.Screen name="Me" component={Test} options={{ tabBarIcon: ({ color }) => (<Feather name="user" size={24} color={color} />) }} />
</Tab.Navigator>
)
}
But it doesnt show the right material-bottom-tabs-navigator.
It shows this:
Image of wrong navigator
Show right material-bottom-tabs-navigator but it actually shows the bottomnavigation from react-native-paper

React drawer Navigation lags while opening

I am nesting a drawer navigation on top of a stack navigator. It works, but the problem is that it lags excessively while opening the drawer. What could be the issue here?
import React, { useEffect, useState } from "react";
import CartIcon from "../CartIcon";
import Home from "../../screens/Home";
import Orders from "../../screens/Orders";
import ProductsScreen from "../../screens/ProductsScreen";
import Cart from "../../screens/Cart";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import HomeHeader from "../HomeHeader";
import OrdersDetails from "../../screens/OrdersDetails";
import { createDrawerNavigator } from "#react-navigation/drawer";
const Drawer = createDrawerNavigator()
const Stack = createNativeStackNavigator();
My drawer navigator here
const HomeScreen=()=> {
return (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} options={() => ({
title: "BarPoint",
headerRight: () => <HomeHeader />,
})} />
</Drawer.Navigator>
);
}
stack navigator here
const AppStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="ProductsScreen"
component={ProductsScreen}
options={({ navigation }) => ({
title: "Products",
headerRight: () => <CartIcon navigation={navigation} />,
})}
/>
<Stack.Screen name="Cart" component={Cart} />
<Stack.Screen name="Orders" component={Orders} />
<Stack.Screen name="OrdersDetails" component={OrdersDetails} />
</Stack.Navigator>
);
};
export default AppStack;
Add useLegacyImplementation in Drawer.Navigator and compile.
const HomeScreen=()=> {
return (
<Drawer.Navigator
useLegacyImplementation //<- Add here
>
<Drawer.Screen name="Home" component={Home} options={() => ({
title: "BarPoint",
headerRight: () => <HomeHeader />,
})} />
</Drawer.Navigator>
);
}
It occurred an Error to me by adding useLegacyImplementation.
Here is my code.Also,I can't touch off my sidebar by navigation.openDrawer
my devices: xcode13 react-navigation6.x
import React ,{Component}from 'react';
import { Button, View ,Text,StyleSheet} from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer=createDrawerNavigator()
//two function
function HomeScreen(prop){
return(
<View style={styles.container}>
<Text style={styles.text}>Home Screen</Text>
<Button title={"Open Drawer"} onPress={()=>prop.navigation.openDrawer()}/>
<Button title={"Toggle Drawer"} onPress={()=>prop.navigation.toggleDrawer()}/>
</View>
)
}
function NewsScreen(prop){
return(
<View style={styles.container}>
<Text style={styles.text}>News Screen</Text>
<Button title={"jump to Home"} onPress={()=>prop.navigation.navigate('Home')}/>
</View>
)
}
export default class index extends Component{
render(){
return(
<Drawer.Navigator useLegacyImplementation={true} >
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="News" component={NewsScreen} />
</Drawer.Navigator>
)
}
}
const styles=StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
alignItems: 'center',
},
text:{
fontSize:40
}
})

Navigation undefined - TypeError: undefined is not an object (evaluating 'navigation.navigate')

I'm facing problem using navigation prop for the header button on the Home screen. It seems the problem is the Navaigation prop can't be rendered. Can someone help me clear this issue? I spent some good amount of time reading the document, but can't go further. Thanks!
import * as React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import Home from '../screens/Shop/Home';
import ProductDetails from '../screens/Shop/ProductDetails';
import Colors from '../constants/Colors';
import {Ionicons} from '#expo/vector-icons';
import {
HeaderButtons,
HeaderButton,
Item,
} from 'react-navigation-header-buttons';
import Cart from '../screens/Shop/Cart';
import {NavigationContainer, useNavigation} from '#react-navigation/native';
const IoniconsHeaderButton = (props) => (
<HeaderButton
IconComponent={Ionicons}
iconSize={23}
color="white"
{...props}
/>
);
const Stack = createStackNavigator();
export default ShopNavigator = ({navigation}) => {
return (
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: Colors.accent,
},
headerTintColor: 'white',
headerTitleStyle: {
fontFamily: 'balsamiq-regular',
},
}}
>
<Stack.Screen
name="Home"
component={Home}
options={{
headerRight: () => (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item
title="search"
iconName="cart-outline"
onPress={() => navigation.navigate('Cart')}
/>
</HeaderButtons>
),
}}
/>
<Stack.Screen
name="ProductDetails"
component={ProductDetails}
options={({route}) => ({title: route.params.itemTitle})}
/>
<Stack.Screen name="Cart" component={Cart} />
</Stack.Navigator>
);
};
Basically, you are just not passing the navigation params that is returned by options. That's why the undefined error is coming
Change this
options={{
headerRight: () => (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item
title="search"
iconName="cart-outline"
onPress={() => navigation.navigate('Cart')}
/>
</HeaderButtons>
),
}}
to this
options={({ navigation }) => ({
headerRight: () => (
<HeaderButtons HeaderButtonComponent={IoniconsHeaderButton}>
<Item
title="search"
iconName="cart-outline"
onPress={() => navigation.navigate('Cart')}
/>
</HeaderButtons>
),
})}

How can I hide the bottom tab bar on a specific screen (react navigation 5.x)

I wanted to know how to hide the bottom tab bar from a specific screen inside my stack navigator, my code is below. I just want to hide bottom tabs for the Player screen, or open Player screen with modal can anyone help me?
This is my code for my main tab navigator
import React from 'react';
import { StatusBar } from 'react-native';
import { NavigationContainer, DarkTheme } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
//views
import HomeStack from './src/views/Home';
import SearchStack from './src/views/Search';
import MoviesStack from './src/views/Movies';
import SeriesStack from './src/views/Series';
import Other from './src/views/Other';
//icons
import {
HomeIcon,
SearchIcon,
MovieIcon,
SeriesIcon,
OtherIcon,
} from './src/components/icons';
const Tab = createBottomTabNavigator();
export default function App() {
return (
<>
<StatusBar barStyle="dark-content" />
<NavigationContainer theme={DarkTheme}>
<Tab.Navigator
initialRouteName="Home"
tabBarOptions={{
activeTintColor: 'white',
keyboardHidesTabBar: false,
}}
>
<Tab.Screen
name="Home"
component={HomeStack}
options={{
tabBarLabel: 'Home',
tabBarIcon: ({ focused }) => (
<HomeIcon
fill={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Search"
component={SearchStack}
options={{
tabBarLabel: 'Search',
tabBarIcon: ({ focused }) => (
<SearchIcon
stroke={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Movie"
component={MoviesStack}
options={{
tabBarLabel: 'Movie',
tabBarIcon: ({ focused }) => (
<MovieIcon
color={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Series"
component={SeriesStack}
options={{
tabBarLabel: 'Series',
tabBarIcon: ({ focused }) => (
<SeriesIcon
color={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
<Tab.Screen
name="Other"
component={Other}
options={{
tabBarLabel: 'Other',
tabBarIcon: ({ focused }) => (
<OtherIcon
fill={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
}}
/>
</Tab.Navigator>
</NavigationContainer>
</>
);
}
This is my code for my main stack navigator
import React from 'react';
import { View, Image } from 'react-native';
import { createStackNavigator } from '#react-navigation/stack';
//components
import Screen from '../components/Screen';
import HomeList from '../components/HomeList';
//views
import MovieDetail from './MovieDetail';
import SeriesDetail from './SeriesDetail';
import Player from './Player';
function Home({ navigation }) {
return (
<Screen>
<View>
<Image source={require('../../assets/logo.png')} />
...
</View>
</Screen>
);
}
const Stack = createStackNavigator();
export default function HomeStack() {
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="MovieDetail" component={MovieDetail} />
<Stack.Screen name="SeriesDetail" component={SeriesDetail} />
<Stack.Screen name="Player" component={Player} />
</Stack.Navigator>
);
}
and this is my code for stack navigator of the page I use to send data to the page i want to hide
import React from 'react';
import {
View,
Text,
TouchableOpacity,
} from 'react-native';
//components
import Screen from '../components/Screen';
import Loading from '../components/Loading';
export default function MovieDetail({ route, navigation }) {
const { id, title } = route.params;
return (
<Screen>
<TouchableOpacity
activeOpacity={0.7}
onPress={() =>
navigation.navigate('Player', {
uri: 'https://blabla.com',
})
}
>
<PlayIcon color="black" />
<Text>
Play
</Text>
</TouchableOpacity>
</Screen>
);
}
and here I want to hide tab bar this screen
import React from 'react';
import WebView from 'react-native-webview';
export default function Player({ route }) {
const { uri } = route.params;
return (
<WebView source={{ uri }} />
);
}
Ciao, you can hide bottom tabbar in Player screen like that:
Modify your Tab.Screen Home like this:
<Tab.Screen
name="Home"
component={HomeStack}
options={({ route }) => ({
tabBarLabel: 'Keşfet',
tabBarIcon: ({ focused }) => (
<HomeIcon
fill={focused ? 'white' : 'gray'}
width={24}
height={24}
/>
),
tabBarVisible: getTabBarVisibility(route),
})}
/>
Then create getTabBarVisibility function to check that the name of the root is Player:
const getTabBarVisibility = (route) => {
const routeName = route.state
? route.state.routes[route.state.index].name
: '';
if (routeName === 'Player') {
return false;
}
return true;
};
That's it. Now if you navigate into Player page, tabBar disappears.

Is is possible to use navigation.toggleDrawer() in navigation options

In my navigation file , when I want to toggle drawer , get the following error :
TypeError: navigation.openDrawer is not a function.(In
'navigation.openDrawer()', 'navigation.openDrawer' is undefined)
This is my drawer:
const DrawerNavigator = () => {
return (
<Drawer.Navigator
initialRouteName="MYSHIFT"
>
<Drawer.Screen name="MYSHIFT" component={TopTabNavigator} />
</Drawer.Navigator>
)
}
And this is my container navigation :
const CareworkerNavigation = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }} />
<Stack.Screen
name="Main"
options={({ navigation }) => {
return {
headerLeft: () => <Button title="LEFT BUTTON" onPress={() => {
navigation.toggleDrawer(); // <--- this line throws an error
}} />
}
}}
component={DrawerNavigator} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default CareworkerNavigation
Why I can not use navigation.toggleDrawer() in navigation options?
Is is possible to remove this problem ?
If you check the React Navigation docs, "You will need to make the drawer navigator the parent of any navigator where the drawer should be rendered on top of its UI."
React Navigation docs reference
To answer your question : Yes , it is possible.
And here you have a working example:
import React from 'react'
import { Button, View } from 'react-native'
import { NavigationContainer } from '#react-navigation/native'
import { createDrawerNavigator } from '#react-navigation/drawer'
import { createStackNavigator } from '#react-navigation/stack'
const Feed = () => <View />
const Notifications = () => <View />
const Profile = () => <View />
const FeedStack = createStackNavigator()
const Home = ({ navigation }) => (
<FeedStack.Navigator>
<FeedStack.Screen
name="Feed"
component={Feed}
options={props => {
const { toggleDrawer } = props.navigation // <-- drawer's navigation (not from stack)
return {
headerLeft: () => <Button title="LEFT BUTTON" onPress={toggleDrawer} />
}
}}
/>
</FeedStack.Navigator>
)
const Drawer = createDrawerNavigator()
export default props => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Feed">
<Drawer.Screen
name="Feed"
component={Home}
options={{ drawerLabel: 'Home' }}
/>
<Drawer.Screen
name="Notifications"
component={Notifications}
options={{ drawerLabel: 'Updates' }}
/>
<Drawer.Screen
name="Profile"
component={Profile}
options={{ drawerLabel: 'Profile' }}
/>
</Drawer.Navigator>
</NavigationContainer>
)
}
While constructing navigation at options, you refer to the navigation of the stack, what cant perform draw actions, try to construct it on header itself
<Stack.Screen
name="Main"
options={() => {
return {
headerLeft: (navigation) => <Button title="LEFT BUTTON" onPress={() => {
navigation.toggleDrawer(); // <--- this line throws an error
}} />
}
}}
component={DrawerNavigator} />
https://github.com/react-navigation/react-navigation/issues/55