Tab bottom navigation react native - reactjs

I new in react-native and junior developer.
I'm using react-native v0.70.6
#react-navigation/stack and #react-navigation/bottom-tabs.
My tab bottom component looks like this:
<Tab.Navigator
initialRouteName='Home'
screenOptions={{
headerShown:false,
tabBarShowLabel:false,
tabBarStyle:style.tabsBottomContainer
}}
sceneContainerStyle={style.backgroundContent}
>
<Tab.Screen
name='Assets'
component={AssetScreen}
options={{unmountOnBlur:true,tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconAsset}
style={{
tintColor: focused ? '#00B2DF' : '',
marginTop: 8
}}
/>
</View>
)}}
/>
<Tab.Screen
name='Bluetooth'
component={ConnectScreen}
children = {()=> <NotFoundGateway />}
options={{unmountOnBlur:true,tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconBluetooth}
style={{
tintColor: focused ? '#00B2DF' : ''
}}
/>
</View>
)}}
/>
<Tab.Screen
name='Home'
component={HomeScreen}
options={{unmountOnBlur:true,tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconHome}
style={{
tintColor: focused ? '#00B2DF' : ''
}}
/>
</View>
)}}
/>
</Tab.Navigator>
Inside index.tsx I have a navigation that does not need the bottom tabs. For example the Login. -->
<NavigationContainer>
<Stack.Navigator initialRouteName='tabsBottomHome'>
{state.isSignIn ? (
<>
<Stack.Screen
name='tabsBottomHome'
component={TabsBottomHome}
options={headerOptions}
/>
):(
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="LoginError"
component={LoginError}
options={headerOptions}
/>
)
</>
)}
</Stack.Navigator>
</NavigationContainer>
The components between the bottom tabs are displayed perfectly. But since I add secondary components to my navigation. For example, I enter the Bluetooth component, within that component I have to enter another component, without losing the bottom tabs.
What would be the correct way to do it?
And how could I set all the routes inside my tabs bottom component?

Solved!
I had to change my navigation structure as follows :
my main structure is like this-->
<NavigationContainer>
<Stack.Navigator initialRouteName='tabsBottomHome'
screenOptions={{
headerTitle: () => <Header />,
headerBackground: () => <HeaderBackground />,
headerLeft: ({ onPress, canGoBack }) =>
canGoBack ? (
<Pressable onPress={onPress} style={{ width: 30, height: 15 }}>
<ArrowLeft height={15} width={15} style={{ marginLeft: 15 }} />
</Pressable>
) : (
<Pressable style={{ width: 65, height: 35 }}></Pressable>
),
headerRight: () => <HeaderRight />,
}}
>
{state.isSignIn ? (
<>
<Stack.Screen
name='tabsBottomHome'
component={TabsBottomHome}
options={{headerShown: false }}
/>
</>
) : (
<>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="LoginError"
component={LoginError}
/>
</>
)}
</Stack.Navigator>
</NavigationContainer>
my tab bottom navigation structure looks like this
<Tab.Navigator
initialRouteName='Home'
screenOptions={{
headerShown:true,
tabBarShowLabel:false,
tabBarStyle:style.tabsBottomContainer,
unmountOnBlur: true,
headerTitle: () => <Header />,
headerBackground: () => <HeaderBackground />,
headerLeft: () =>
routeName != "Home" ? (
<Pressable onPress={navigateBack} style={{ width: 65, height: 15 }}>
<ArrowLeft height={15} width={15} style={{ marginLeft: 15 }} />
</Pressable>
)
: (
<Pressable style={{ width: 65, height: 35 }}></Pressable>
)
,
headerRight: () => <HeaderRight />,
}}
sceneContainerStyle={style.backgroundContent}
screenListeners={({route})=>({
state: ()=> {
setRouteName(route.name);
}
})}
backBehavior={'history'}
>
<Tab.Screen
name='Assets'
component={AssetScreen}
options={{tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconAsset}
style={{
tintColor: focused ? '#00B2DF' : '',
marginTop: 8
}}
/>
</View>
)}} />
<Tab.Screen
name='GatewayStack'
component={ConnectGatewayStack}
options={{tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconBluetooth}
style={{
tintColor: focused ? '#00B2DF' : ''
}}
/>
</View>
)}} />
</Tab.Navigator>
And my ConnectGatawayStack structure contains the navigation of all that Tab, therefore it is inside my Tab and the focus is not lost and it works correctly. Obviously now I am facing a goBack problem. but that's another kind of problem.
ConnectGatawayStack -->
export type StackConnectList = {
Connect: undefined;
QRScan: undefined;
GatewayList: undefined;
GatewayInfo: undefined;
NotFoundGateway: undefined;
GatewayDetected: undefined;
ErrorConnecting: undefined;
}
const GatewayStack = createStackNavigator<StackConnectList>();
const ConnectGatewayStack = () =>{
return (
<GatewayStack.Navigator initialRouteName='Connect'
screenOptions={{headerShown:false}}
>
<GatewayStack.Screen name='Connect' component={ConnectScreen} />
<GatewayStack.Screen name='GatewayList' component={GatewayList} />
<GatewayStack.Screen name='GatewayInfo' component={GatewayInfo} />
<GatewayStack.Screen name='QRScan' component={QRScanScreen} />
<GatewayStack.Screen name='NotFoundGateway' component={NotFoundGateway} />
<GatewayStack.Screen name='GatewayDetected' component={GatewayDetected} />
<GatewayStack.Screen name='ErrorConnecting' component={ErrorConnecting} />
</GatewayStack.Navigator>
)
}
export {ConnectGatewayStack};
Thanks!

Related

goBack not working in nested navigators react native. TabNavigator and StackNavigator

I have this problem several days ago and I can't find a solution.
This is my navigation structure
Index.tsx -->
<NavigationContainer>
<Stack.Navigator initialRouteName='tabsBottomHome'
screenOptions={{
headerTitle: () => <Header />,
headerBackground: () => <HeaderBackground />,
headerLeft: ({ onPress, canGoBack }) =>
canGoBack ? (
<Pressable onPress={onPress} style={{ width: 30, height: 15 }}>
<ArrowLeft height={15} width={15} style={{ marginLeft: 15 }} />
</Pressable>
) : (
<Pressable style={{ width: 65, height: 35 }}></Pressable>
),
headerRight: () => <HeaderRight />,
}}
>
{state.isSignIn ? (
<>
<Stack.Screen
name='tabsBottomHome'
component={TabsBottomHome}
options={{headerShown: false }}
/>
</>
) : (
<>
<Stack.Screen
name="Login"
component={LoginScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="LoginError"
component={LoginError}
/>
</>
)}
</Stack.Navigator>
</NavigationContainer>
This would be the first navigation of my application. So far everything is going well.
TabsBottomNavigation -->
<Tab.Navigator
initialRouteName='Home'
screenOptions={{
headerShown:true,
tabBarShowLabel:false,
tabBarStyle:style.tabsBottomContainer,
unmountOnBlur: true,
headerTitle: () => <Header />,
headerBackground: () => <HeaderBackground />,
headerLeft: () =>
routeName != "Home" ? (
<Pressable onPress={navigateBack} style={{ width: 65, height: 15 }}>
<ArrowLeft height={15} width={15} style={{ marginLeft: 15 }} />
</Pressable>
)
: (
<Pressable style={{ width: 65, height: 35 }}></Pressable>
)
,
headerRight: () => <HeaderRight />,
}}
sceneContainerStyle={style.backgroundContent}
screenListeners={({route})=>({
state: ()=> {
setRouteName(route.name);
}
})}
backBehavior={'history'}
>
<Tab.Screen
name='Assets'
component={AssetScreen}
options={{tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconAsset}
style={{
tintColor: focused ? '#00B2DF' : '',
marginTop: 8
}}
/>
</View>
)}} />
<Tab.Screen
name='GatewayStack'
component={ConnectGatewayStack}
options={{tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconBluetooth}
style={{
tintColor: focused ? '#00B2DF' : ''
}}
/>
</View>
)}} />
<Tab.Screen
name='Home'
component={HomeScreen}
options={{tabBarIcon:({focused,color})=>(
<View>
<Image
source={iconHome}
style={{
tintColor: focused ? '#00B2DF' : ''
}}
/>
</View>
)
}} />
</Tab.Navigator>
everything is fine here too, the conflict is in the ConnectGatewayStack stack
ConnectGatewayStack -->
export type StackConnectList = {
Connect: undefined;
QRScan: undefined;
GatewayList: undefined;
GatewayInfo: undefined;
NotFoundGateway: undefined;
GatewayDetected: undefined;
ErrorConnecting: undefined;
}
const GatewayStack = createStackNavigator<StackConnectList>();
const ConnectGatewayStack = () =>{
return (
<GatewayStack.Navigator initialRouteName='Connect'
screenOptions={{headerShown:false}}
>
<GatewayStack.Screen name='Connect' component={ConnectScreen} />
<GatewayStack.Screen name='GatewayList' component={GatewayList} />
<GatewayStack.Screen name='GatewayInfo' component={GatewayInfo} />
<GatewayStack.Screen name='QRScan' component={QRScanScreen} />
<GatewayStack.Screen name='NotFoundGateway' component={NotFoundGateway} />
<GatewayStack.Screen name='GatewayDetected' component={GatewayDetected} />
<GatewayStack.Screen name='ErrorConnecting' component={ErrorConnecting} />
</GatewayStack.Navigator>
)
}
export {ConnectGatewayStack};
When I navigate to the ConnectGatewayStack tab, which contains the other components that I just showed, if I go to a child component and press the back button in header, it returns directly to the TabsBottomHome (that is, to the Tabs navigation) and not to the component that was previously visited.
For the navigation back, i use
import { useNavigation } from '#react-navigation/core';
whit
const navigation = useNavigation();
navigation.goback();
I tried whit diferents methods, but none solved my problem.
example test whit
backBehavior={'history'}
backBehavior={'order'}
and many functions of the core react-native and react-native-navigation
any ideas?
sorry for my bad english and thank you very much

React Native Navigation v5 - Whats wrong with my navigation Setup?

I have a problem depending the Navigator setup that is used with Version 5 of React Navigation.
Here is my Code:
import React from "react";
import { LogBox, Platform, TouchableOpacity } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack"
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import {
Auth,
Monatsübersicht2,
StundenChecken,
StundenEintragen,
Logout,
TagesübersichtDiff,
StundenEdit,
MonatsberichtComponent,
} from "../screens/index";
import Icon from "react-native-vector-icons/Ionicons";
import AsyncStorage from "#react-native-async-storage/async-storage";
LogBox.ignoreAllLogs();
const Stack = createStackNavigator();
function EintragenStack() {
return (
<Stack.Navigator initialRouteName="Eintragen">
<Stack.Screen
name="Eintragen"
component={StundenEintragen}
options={{
headerTitle: "Stundenverwaltung",
headerTitleStyle: {
color: "white",
alignSelf: "center",
},
headerStyle: {
backgroundColor: "#a51717",
},
headerRight: () => (
<TouchableOpacity onPress={console.log("unlockUserHandler")}>
<Icon
style={{ paddingRight: 20 }}
size={25}
color="white"
name="lock-open"
/>
</TouchableOpacity>
),
}}
/>
</Stack.Navigator>
)};
function CheckStack(){
return (
<Stack.Navigator initialRouteName="Übersicht" >
<Stack.Screen
name="Übersicht"
component={StundenChecken}
/>
<Stack.Screen
name="Monat"
component={Monatsübersicht2}
options={({navigation}) => ({
title: "Monatsübersicht"
})}
/>
<Stack.Screen
name="Tag"
component={TagesübersichtDiff}
options={({navigation}) => ({
headerRight: () => (
<TouchableOpacity onPress={() => console.log("Ahllo")}>
<Icon
style={{ paddingRight: 20 }}
size={25}
color="#a51717"
name="lock-open"
/>
</TouchableOpacity>
),
title: "Tagesübersicht"
})}
/>
<Stack.Screen
name="Edit"
component={StundenEdit}
options={{
headerTitle: "Stunden bearbeiten",
headerTitleStyle: {
color: "white",
alignSelf: "center",
},
headerStyle: {
backgroundColor: "#F39237",
},
headerRight: () => (
<TouchableOpacity onPress={console.log("unlockUserHandler")}>
<Icon
style={{ paddingRight: 20 }}
size={25}
color="white"
name="lock-open"
/>
</TouchableOpacity>
),
}}
/>
</Stack.Navigator>
)}
const Tab = createBottomTabNavigator();
function Tabs() {
return (
<Tab.Navigator
initialRouteName="Eintragen"
screenOptions={{
backBehavior: "history",
resetOnBlur: true,
tabBarOptions: {
labelStyle: {
fontSize: 12,
color: "black",
},
showIcon : true,
activeTintColor: "red",
activeBackgroundColor: "#ccc",
}
}}>
<Tab.Screen name="Eintragen" component={EintragenStack} options={{ tabBarIcon:() => (<Icon name="add-circle-outline" size={Platform.OS == "ios" ? 30 : 28} color={"green"} />)}}/>
<Tab.Screen name="Übersicht" component={CheckStack} options={{ tabBarIcon:() => (<Icon name="calendar" size={Platform.OS == "ios" ? 30 : 28} color={"black"} />)}}/>
<Tab.Screen name="Monatsbericht" component={MonatsberichtComponent} options={{headerTitle: "Monatsbericht abschließen", tabBarIcon:() => (<Icon name="download" size={Platform.OS == "ios" ? 30 : 28} color={"black"} />)}}/>
<Tab.Screen name="Logout" component={Logout} options={{ tabBarIcon:() => (<Icon name="power" size={Platform.OS == "ios" ? 30 : 28} color={"red"} />)}}/>
</Tab.Navigator>
)
}
const AppNavigator = () => {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false,
headerLeft: null,
gestureEnabled: false
}}
>
<Stack.Screen name="Auth" component={Auth} />
<Stack.Screen name="Tabs" component={Tabs} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default function App() {
return <AppNavigator/>;
}
Now in my Auth Screen I can navigate to Tabs - so basically Log into the App by calling:
navigation.replace("Tabs");
But when I try to navigate to my CheckStack for example it wont work and I get thrown this error:
The Call: navigation.replace("CheckStack");
The Error:
ERROR The action 'REPLACE' with payload {"name":"CheckStack"} was not handled by any navigator.
Do you have a screen named 'CheckStack'?
So basically the fix is that my "CheckStack" has to be inside the StackNavigator that is used in NavigationContainer - otherwise it wont be able to use navigation inside.
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false,
headerLeft: null,
gestureEnabled: false
}}
>
<Stack.Screen name="Auth" component={Auth} />
<Stack.Screen name="Tabs" component={Tabs} />
<Stack.Screen name="CheckStack" component={CheckStack} />
</Stack.Navigator>
</NavigationContainer>
the problem is that you are referring to the name of the function and not specifically to the name of the screen
It's screen name
navigation.replace("Tabs");
It's a function not screen name
navigation.replace("CheckStack");

hide header on a stackNavigator screen that is inside DrawerNavigator

I have a stackNavigator (with 2 screens - Home and Details) inside DrawerNavigator,the stackNavigator is a option in the DrawerNavigator.
how can I hide the header only in the DetailsScreen ?
I tried put props headerShown:false, but doesn't work
this is my code.
I'm a little new with this.
export const MenuLateral = () => {
return (
<Drawer.Navigator drawerContent={props => <MenuInterno {...props} />}>
<Drawer.Screen
name="HomeNavigation"
component={HomeNavigation}
options={{title: 'Home'}}
/>
<Drawer.Screen
name="UserProfileScreen"
component={UserProfileScreen}
options={{title: 'My profile'}}
/>
</Drawer.Navigator>
);
};
const MenuInterno = ({navigation}: any) => {
return (
<DrawerContentScrollView>
{/* Parte del avatar */}
<View>
<Image
source={{
uri: 'https://medgoldresources.com/wp-content/uploads/2018/02/avatar-placeholder.gif',
width: 280,
height: 120,
}}
/>
</View>
{/* Opciones de menú */}
<View>
<TouchableOpacity
style={style.flexRow}
onPress={() => navigation.navigate('HomeNavigation')}>
<Text> Home Screen</Text>
</TouchableOpacity>
<TouchableOpacity
style={style.flexRow}
onPress={() => navigation.navigate('UserProfileScreen')}>
<Text> Profile</Text>
</TouchableOpacity>
</View>
</DrawerContentScrollView>
);
};
export type RootStackParams = {
HomeScreen: undefined; //Si no recibe nada como parametro se envia undefined
DetailScreen: any;
};
const Stack = createStackNavigator<RootStackParams>();
export const HomeNavigation = () => {
return (
<Stack.Navigator screenOptions={{headerShown: false, title: 'Home'}}>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
<Stack.Screen
name="DetailScreen"
component={DetailScreen}
options={{headerShown: false}}
/>
</Stack.Navigator>
);
};
I've tested your code on my device and it's working snack link
EDITED
You may try this
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{ headerShown: true, title: 'Home' }}
/>
<Stack.Screen
name="DetailScreen"
component={DetailScreen}
options={{ headerShown: false }}
/>

React Native Nested Stack Inside BottomTabNavigator issue

The navigation process I want to achieve is (BottomTabNavigator -> RoutinesStackNavigator -> Routines) which I'm using a stack navigator nested inside a bottom tab navigator
When I navigate to the RoutinesStackNavigator it isn't loading the Routines page and I am not sure why.
BottomTabNavigation.tsx
export default function Navigation() {
return (
<>
<SoundProvider>
<TimerProvider>
<NavigationContainer>
<Tab.Navigator
sceneContainerStyle={{ backgroundColor: COLORS.white }}
initialRouteName="Pomodoro"
screenOptions={({ route, navigation }) => ({
tabBarShowLabel: false,
headerShown: false,
tabBarStyle: [styles.tabBar, styles.tabBarBoxShadow],
tabBarIcon: ({ focused }) => {
let rn = route.name;
let iconTag;
// assigning navigation icon based on name of route
if (rn === pomodoroName) {
// assigning JSX Tag
iconTag = (
<PomodoroIcon
size={iconSize}
fillColor={iconColor}
isFocused={focused}
/>
);
} else if (rn === agendaName) {
iconTag = (
<AgendaIcon
size={iconSize}
fillColor={iconColor}
isFocused={focused}
/>
);
} else if (rn === tutorialsName) {
iconTag = (
<TutorialsIcon
size={iconSize}
fillColor={iconColor}
isFocused={focused}
/>
);
} else if (rn === routinesStackNavigatorName) {
iconTag = (
<RoutinesIcon
size={iconSize}
fillColor={iconColor}
isFocused={focused}
/>
);
}
return (
<Pressable
onPress={() => {
// add haptic feedback and navigate to new route
addLightHapticFeedback("light");
navigation.navigate(rn);
}}
>
{iconTag}
</Pressable>
);
},
})}
>
<Tab.Screen name={pomodoroName} component={Pomodoro} />
<Tab.Screen name={agendaName} component={Agenda} />
<Tab.Screen name={tutorialsName} component={Tutorials} />
<Tab.Screen
name={routinesStackNavigatorName}
component={RoutinesStackNavigator}
/>
</Tab.Navigator>
</NavigationContainer>
</TimerProvider>
</SoundProvider>
</>
);
}
RoutinesStackNavigator.tsx
export default function RoutinesStackNavigator() {
const Stack = createStackNavigator();
return (
<>
<SafeAreaView>
<Stack.Navigator initialRouteName="Routines">
<Stack.Screen name="Routines" component={Routines} />
<Stack.Screen name="CreateRoutine" component={CreateRoutine} />
</Stack.Navigator>
</SafeAreaView>
</>
);
}
index.Routines.tsx
export default function Routines() {
const { width } = useWindowDimensions();
return (
<>
<FocusedStatusBar barStyle="light-content" />
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.title}>{STRINGS.routinesTitle}</Text>
<TouchableOpacity onPress={() => {}}>
<AntDesign name="pluscircle" size={44} color={COLORS.white} />
</TouchableOpacity>
</View>
<View style={[styles.main, { width: width }]}>
<View style={{ height: "72%" }}>
<ScrollView
showsVerticalScrollIndicator={true}
style={{ marginTop: 10, marginBottom: 10 }}
>
<RoutineCard />
<RoutineCard />
</ScrollView>
</View>
<TouchableOpacity style={styles.button} onPress={() => {}}>
<Text style={styles.buttonText}>Start Session</Text>
</TouchableOpacity>
</View>
</View>
</>
);
}
none of the Routines component renders, except the StatusBar color changes. So the component must be rendering but the rest of the content doesn't show up.
You have to remove <SafeAreaView> from RoutinesStackNavigator.tsx
const Stack = createStackNavigator();
export default function RoutinesStackNavigator() {
return (
<Stack.Navigator initialRouteName="Routines">
<Stack.Screen name="Routines" component={Routines} />
<Stack.Screen name="CreateRoutine" component={CreateRoutine} />
</Stack.Navigator>
);
}

How do I apply external/global style to a react-navigation bottom tab

I tried to apply a global style to a bottom tab navigation in react-native but it can't accept it in the screenOptions prop. But it works fine when I use normal inline styling. Please help
export default function CustomBottomTab() {
return (
<Tab.Navigator
screenOptions={{
tabBarStyle: {styles.customTab} //underlines the dot as an error
}}
>
<Tab.Screen
name='Landing'
component={HomeScreen}
options={{
tabBarIcon: (props) => <AntDesign name='home' size={20} {...props} />,
}}
/>
<Tab.Screen
name='Notifications'
component={NotifScreen}
options={{
tabBarIcon: (props) => (
<FontAwesome5 name='bell' size={20} {...props} />
),
}}
/>
<Tab.Screen
name='Wishlist'
component={WishScreen}
options={{
tabBarIcon: (props) => (
<Ionicons name='bookmarks-outline' size={20} {...props} />
),
}}
/>
<Tab.Screen
name='Messages'
component={MessagesScreen}
options={{
tabBarIcon: (props) => (
<FontAwesome5 name='comment' size={20} {...props} />
),
}}
/>
</Tab.Navigator>
);
}
Remove {} from around {styles.customTab}. It's not valid JavaScript syntax.
It needs to be:
tabBarStyle: styles.customTab

Resources