Mixing both Stack navigation and tab navigation in react native - react-native

I'm trying to mix stack navigation and tab navigation i have 14 Screens:
Search,
Home,
CartTab,
SideBar,
Details,
PriceComparison,
ShopByCategory,
ShopByStore,
CategoryPage,
CategoryFilter,
Checkout,
Login,
Register,
ForgotPassword
I want to have Search, Home, CartTab, Sidebar as bottom navigation and the other pages as stack navigation, with SearchBy pages, Details, Price Comparison not displaying the bottom tab. I'm new to react native and i have been trying diffrent solutions however 1) i'm not able to remove the bottomtab from the wanted screens and 2) using navigation.navigate is returning me errores example using navigation.navigate('Category'); i get an error The action 'NAVIGATE' with payload {"name":"Category"} was not handled by any navigator. Do you have a screen named 'Category'?
This is my code :
StackNavigator.js:
import React from 'react'
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
import {
CartTab,
Details,
Home,
Notification,
PriceComparison,
Search,
SplashScreen,
ShopByCategory,
ShopByStore,
CategoryPage,
Checkout,
CategoryFilter,
Login,
Register,
ForgotPassword
} from '../screens';
import { SideBar } from './../components';
export const MainStackNavigator = () => {
const Stack = createStackNavigator();
return (
<Stack.Navigator screenOptions={{headerShown: false}} initialRouteName={'Home'}>
{/*<Stack.Screen name="SplashScreen" component={SplashScreen} /> */}
<Stack.Screen name="Login" component={Login} options={{ tabBarVisible: false }} />
<Stack.Screen name="Register" component={Register} options={{ tabBarVisible: false }} />
<Stack.Screen name="Recovery" component={ForgotPassword} options={{ tabBarVisible: false }} />
<Stack.Screen name="Home" component={Home} options={{ tabBarVisible: false }} />
<Stack.Screen name="Notification" component={Notification} />
<Stack.Screen name="Comparison" component={PriceComparison} options={{ tabBarVisible: false }} />
<Stack.Screen name="ShopByCategory" component={ShopByCategory}/>
<Stack.Screen name="ShopByStore" component={ShopByStore}/>
{/*<Stack.Screen name="Category" component={CategoryPage}/>
<Stack.Screen name="CategoryFilter" component={CategoryFilter}/>*/}
</Stack.Navigator>
);
}
export const CartStackNavigator = () => {
const Stack = createStackNavigator();
return (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="Cart" component={CartTab} />
<Stack.Screen name="Checkout" component={Checkout}/>
</Stack.Navigator>
);
}
export const SearchStackNavigator = () => {
const Stack = createStackNavigator();
return (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="Search" component={Search} />
<Stack.Screen name="Details" component={Details}/>
</Stack.Navigator>
);
}
export const SidebarStackNavigator = () => {
const Stack = createStackNavigator();
return (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="Sidebar" component={SideBar} />
<Stack.Screen name="ShopByCategory" component={ShopByCategory}/>
<Stack.Screen name="ShopByStore" component={ShopByStore}/>
<Stack.Screen name="Category" component={CategoryPage}/>
</Stack.Navigator>
);
}
TabNavigation.js:
import 'react-native-gesture-handler';
import React from 'react';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';
import {COLORS} from '../constants';
import { CartStackNavigator, MainStackNavigator, SearchStackNavigator, SidebarStackNavigator }
from '../navigation/StackNavigator';
import { useStateContext } from '../context/StateContext';
const Tab = createBottomTabNavigator();
export const TabNavigation = ({navigation}) => {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
headerShown: false,
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? 'home'
: 'home-outline';
} else if (route.name === 'Cart') {
iconName = focused ? 'cart' : 'cart-outline';
} else if (route.name === 'Search') {
iconName = focused ? 'search' : 'search-outline';
} else if (route.name === 'SideBar') {
iconName = focused ? 'grid' : 'grid-outline';
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
tabBarActiveTintColor: COLORS.primary,
tabBarInactiveTintColor: 'gray',
})}
>
<Tab.Screen name="Home" component={MainStackNavigator} />
<Tab.Screen name="Search" component={SearchStackNavigator} />
<Tab.Screen name="Cart" component={CartStackNavigator} options={{ tabBarBadge: 3, tabBarBadgeStyle: { backgroundColor: COLORS.primary, marginTop: -5 } }}/>
<Tab.Screen name="SideBar" component={SidebarStackNavigator} />
</Tab.Navigator>
);
};
App.js:
import React from "react";
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
import CustomDrawer from './navigation/CustomDrawer'
import {StateContext} from './context/StateContext'
import { Home, CartTab, Search, SideBar, SplashScreen, Notification, Login, Register,
ForgotPassword } from "./screens";
import { Header, TabNavigation } from "./components";
import { StripeProvider } from '#stripe/stripe-react-native';
const Stack = createStackNavigator();
const App = () => {
const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 3000);
}, []);
if (isLoading) {
return <SplashScreen />;
}
return (
<StateContext>
<NavigationContainer>
<TabNavigation/>
</NavigationContainer>
</StateContext>
);
}
export default App

Make two different Stacks file one is StackNavigation and other is BottomNavigation . Render your Stack Navigation and with calling the component of TabNavigation
I used the Dummy names of screens . Replace it according to your screen names
Stack navigation
import { createStackNavigator } from '#react-navigation/stack';
import { NavigationContainer } from '#react-navigation/native';
import {
CartTab,
Details,
Home,
} from '../screens';
import {TabNavigation } from '../navigation/StackNavigator';
export const StackNavigator = () => {
const Stack = createStackNavigator();
return (
<Stack.Navigator screenOptions={{headerShown: false}}
initialRouteName={'Home'}>
<Stack.Screen name="Home" component={TabNavigation}/>
<Stack.Screen name="ShopByCategory" component={ShopByCategory}/>
<Stack.Screen name="ShopByStore" component={ShopByStore}/>
<Stack.Screen name="CategoryFilter" component={CategoryFilter}/>
</Stack.Navigator>
);
}
Bottom Tab Navigation
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
export const TabNavigation = ({navigation}) => {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
headerShown: false}
})}>
<Tab.Screen name="Example" component={Example} />
<Tab.Screen name="Search" component={Search} />
<Tab.Screen name="SideBar" component={SideBar} />
</Tab.Navigator>
);
};

Related

Couldn't find a navigation object

I can not speak English well.
I get an error when I add useFocusEffect function to app.js file.
Error : Couldn't find a navigation object. Is your component inside NavigationContainer?
App.js
import { useState, useCallback } from "react";
import { NavigationContainer, useFocusEffect, } from "#react-navigation/native";
const Stack = createStackNavigator();
function App() {
const [isLogin, setLogin] = useState("");
useFocusEffect(
useCallback(async() => {
//....
}, [isLogin])
);
return (
<NavigationContainer ref={navigationRef}><Stack.Navigator>
{isLogin == "" ? (
<Stack.Group>
<Stack.Screen
name="Home"
component={Home}
options={{ headerShown: false, title: "Anasayfa" }}
/>
</Stack.Group>
) : (
<Stack.Group screenOptions={{ headerShown: false }}>
<Stack.Screen
name="Conference"
component={Conference}
options={{ title: "", headerTintColor: "#000" }}
/>
</Stack.Group>
)}
</Stack.Navigator>
</NavigationContainer>
)
}
export default App;

Combine Drawer.Navigator and Stack.Navigator without creating separate navigation bars

I would like to have stack and drawer navigators use the same navigation bar. However, both are creating their own navigation bars refer to the below image making the app look messy. How can I achieve that?
Below is my code:
import * as React from "react";
import { createStackNavigator } from "#react-navigation/stack";
import { createDrawerNavigator } from "#react-navigation/drawer";
import Home from "../screens/Home";
import Contact from "../screens/Contact";
import About from "../screens/About";
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const HomeNavigation = (props) => {
return (
<Stack.Navigator initialRouteName='Home'
screenOptions={{
headerTitleAlign:'center',
//headerShown: false
}}
>
<Stack.Screen name='Home' component={Home} />
<Stack.Screen name='Contact' component={Contact} />
<Stack.Screen name='About' component={About} />
</Stack.Navigator>
);
};
const MenuNavigation = (props) => {
return (
<Stack.Navigator initialRouteName='Home'
screenOptions={{
headerTitleAlign:'center',
//headerShown: false
}}>
<Stack.Screen name='Menu' component={About} />
</Stack.Navigator>
);
};
const DrawerNavigation = () => {
return (
<Drawer.Navigator>
<Drawer.Screen name='HomeNavigation' component={HomeNavigation} />
<Drawer.Screen name='MenuNavigation' component={MenuNavigation} />
</Drawer.Navigator>
);
};
export default DrawerNavigation;

react navigation version 5, hide top bar when render tab screen

I've created nested navigation using react-navigation version 5, But when tab screen render I need to hide top bar, I've follow step from here https://reactnavigation.org/docs/hiding-tabbar-in-screens/ but still not working
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {navigationRef} from './NavigationService';
import {Home, Appointment, Settings, Map, ProviderDetails} from 'app/screens';
import {PRIMARY_COLOR, SECONDARY_COLOR} from '../config/color';
import ThemeController from '../components/ThemeController';
import {StatusBar} from 'react-native';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
const Stack = createStackNavigator();
const homeOptions = {
title: 'Home',
headerTitleStyle: {
fontWeight: 'bold',
},
headerRight: () => <ThemeController />,
};
const HomeStack = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
</Stack.Navigator>
);
};
const MapStack = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Map" component={Map} />
<Stack.Screen name="ProviderDetails" component={ProviderDetails} />
</Stack.Navigator>
);
};
const Tab = createBottomTabNavigator();
function App(props) {
const {theme} = props;
return (
<NavigationContainer ref={navigationRef} theme={theme}>
<StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />
<Tab.Navigator
screenOptions={({route}) => ({
tabBarIcon: ({focused, color, size}) => {
if (route.name === 'Home') {
return <MaterialIcons name="home" size={size} color={color} />;
} else if (route.name === 'Map') {
return (
<FontAwesome5 name="map-marked-alt" size={size} color={color} />
);
} else if (route.name === 'Appointment') {
return (
<FontAwesome5 name="calendar-alt" size={size} color={color} />
);
} else if (route.name === 'More') {
return (
<MaterialIcons name="more-horiz" size={size} color={color} />
);
}
},
})}
tabBarOptions={{
activeTintColor: PRIMARY_COLOR,
inactiveTintColor: SECONDARY_COLOR,
}}>
<Tab.Screen name="Home" component={HomeStack} />
<Tab.Screen name="Map" component={MapStack} />
<Tab.Screen name="Appointment" component={Appointment} />
<Tab.Screen name="More" component={Settings} />
</Tab.Navigator>
</NavigationContainer>
);
}
export default App;
Create HomeStack and MapStack stack navigator and pass that value to Tab Navigator,
In bellow image you can see in Home and Map tab display top bar.
Use headerShown option
const HomeStack = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Home" options={{ headerShown: false }} component={Home} />
</Stack.Navigator>
);
};

How to combine createStackNavigator createDrawerNavigator in latest version of react navigation v5

In the latest version of react-navigation v5 how to combine createStackNavigator with createDrawerNavigator
This is my main navigator file.
import InitialScreen from '#InitialScreen'
import SignIn from '#SignIn'
import Home from '#Home'
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
class NavigationStack extends Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="InitialScreen" component={InitialScreen} options={{ headerShown: false }}/>
<Stack.Screen name="SignIn" component={SignIn} options={{ headerShown: false }} />
<Stack.Screen name="Home" component={Home} options={{ headerShown: false }} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
export default NavigationStack;
In my Home component I have bottom-tabs
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
class Home extends Component {
render() {
return (
<Tab.Navigator>
<Tab.Screen
name="Documents"
component={Images}
options={{
tabBarLabel: 'Images',
tabBarIcon: ({ focused }) => (
<Image source={Images.iconDocuments}/>
),
}}
/>
<Tab.Screen
name="Profile"
component={Profile}
options={{
tabBarLabel: 'IRROP',
tabBarIcon: ({ focused }) => (
<Image source={Images.iconImages}/>
),
}}
/>
</Tab.Navigator>
)
}
}
export default Home;
I want to include Drawer Navigation in Stack Navigation How can I do it in react-navigation v5

Open the drawer when I click the icon react navigation version 5

I want to open the drawer when I click the icon in the headerLeft part, I also have try to this.props.navigation.dispatch but is gives an error also navigation.dispatch gives error
The code below does not gives errors but is does not open the drawer
import { DrawerActions } from '#react-navigation/native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createStackNavigator } from '#react-navigation/stack';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
export default class App extends Component {
createHomeStack = () =>
<Stack.Navigator>
<Stack.Screen
initialRouteName="login"
headerMode="screen"
name="main"
children={ this.createBottomTabs}
options={{
title: "Fitbit",
headerLeft: () => (
<Icon
name="menu"
size={25}
color="#D4AF37"
onPress={() => {DrawerActions.openDrawer() }}
/>
)} } />
</Stack.Navigator>
createDrawer = ({navigation}) =>
<Drawer.Navigator initialRouteName="Main" >
<Drawer.Screen name="Main" component={Main} />
<Drawer.Screen name="Contacts" component={Food} />>
</Drawer.Navigator>
render() {
return (
<NavigationContainer>
{this.createHomeStack()}
</NavigationContainer>
);
}
}
In order to achieve that you need to wrap the stack into the drawer as the documentation says.
Documentation here
I would probably use something like this:
EDIT:
Added full code
import React,{Component} from 'react'
import { NavigationContainer } from '#react-navigation/native'
import { createDrawerNavigator } from '#react-navigation/drawer'
import { createStackNavigator } from '#react-navigation/stack'
import { View } from 'react-native'
import Icon from 'react-native-vector-icons/dist/Feather'
const Drawer = createDrawerNavigator()
const Stack = createStackNavigator()
const Main = () => <View></View>
const Food = () => <View></View>
const Home = ({ navigation }) => (
<Stack.Navigator>
<Stack.Screen name="Main" component={Main} options={{
headerLeft: () => <Icon
name="menu"
size={25}
color="#D4AF37"
onPress={() => navigation.openDrawer()}
/>
}} />
</Stack.Navigator>
)
const DrawerNavigator = () => (
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Contacts" component={Food} />
</Drawer.Navigator>
)
export default props => (
<NavigationContainer>
<DrawerNavigator />
</NavigationContainer>
)
You need To import DrawerActions
import {DrawerActions } from '#react-navigation/native';
And You Can Open Using
navigation.dispatch(DrawerActions.openDrawer());