React native clear Stack Navigator stack in bottom tab bars - javascript

I am developing an app which has bottom tab navigation. For implementing this , I've used react-navigation-material-bottom-tabs, which is working perfectly fine. Like I have 3 screens ,say Home, Profile and About in the bottom tab navigator. But in the Home screen I have multiple screens flow to be implemented. For that I used Stack Navigator, which is also working fine. So my app flow is like Home-> Screen1-> Screen2-> Screen3 Where I'm facing problem is that suppose I'm on Screen3 and then I switch to Profile screen from bottom navigation, and then again switch to Home screen.
I should be able to see Home Screen there but currently it shows Screen3
Following is my code:
MainTabs.js
import { createStackNavigator } from '#react-navigation/stack';
import Icon from 'react-native-vector-icons/Ionicons';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
const HomeStack = createStackNavigator();
const ProfileStack = createStackNavigator();
const AboutStack = createStackNavigator();
const HomeStackScreen = ({ navigation }) => {
return (
<HomeStack.Navigator screenOptions={{headerShown: false, initialRouteName: 'Screen1'}}>
<HomeStack.Screen name="Screen1" component={Screen1} />
<HomeStack.Screen name="Screen2" component={Screen2} />
<HomeStack.Screen name="Screen3" component={Screen3}/>
</HomeStack.Navigator>
)
}
const ProfileStackScreen = ({ navigation }) => {
return (
<ProfileStack.Navigator screenOptions={{headerShown: false, initialRouteName: 'Profile'}}>
<ProfileStack.Screen name="Profile" component={Profile} />
</ProfileStack.Navigator>
)
}
const AboutStackScreen = ({ navigation }) => {
return (
<AboutStack.Navigator screenOptions={{headerShown: false, initialRouteName: 'About'}}>
<AboutStack.Screen name="About" component={About} />
</AboutStack.Navigator>
)
}
const MainTabScreen = () => {
return (
<Tab.Navigator
initialRouteName="Home"
activeColor="#fff"
barStyle={{ backgroundColor: 'red' }}
labeled={false}
>
<Tab.Screen
name="Home"
component={HomeStackScreen}
/>
<Tab.Screen
name="Profile"
component={ProfileStackScreen}
/>
<Tab.Screen
name="About"
component={AboutStackScreen}
/>
</Tab.Navigator>
);
export default MainTabScreen;

Use navigation.navigate('routeName') when you tap on your bottom tab navigator element. You have to register a route to the first screen of the stack, and from there you can go inside the stack as you like.

set unmountOnBlur options to true.
If you don't mind this.
Normally, we don't recommend enabling this prop as users don't expect their navigation history to be lost when switching tabs. If you enable this prop, please consider if this will actually provide a better experience for the user.
Another way is to pop the stack navigator when leaving screen3.

Related

Issue with React Navigation 6.XX

I have 3 bottom tabs in my home screen stack. The first tab, which is home, has some buttons on it. On click of each button, a new screen is supposed to be displayed. So far, it hasn't worked. I keep getting this error:
The action 'NAVIGATE' with payload {"name":"ScreenName"} was not handled by any navigator.
Do you have a screen named 'ScreenName'?
Here's an overview of my Navigators:
StackNavigator -> Home Screen (BottomNavigator) -> HomeStackScreen(Stack Navigtor)...others are just screens in the bottom navigator for now
In code:
import * as React from 'react'
import { StatusBar, View, StyleSheet } from 'react-native'
import { NavigationContainer, Theme } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack'
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import { navigationRef } from './NavigationService'
const Stack = createNativeStackNavigator()
const AuthStack = createNativeStackNavigator()
const BottomStack = createBottomTabNavigator()
const HomeStack = createNativeStackNavigator()
import Home from 'app/screens/Home'
import Notifications from 'app/screens/WearNotifications'
import ScanCloth from 'app/screens/ScanCloth'
import MyWardrobe from 'app/screens/MyWardrobe'
const HomeStackScreen = () => { // problem occurs with the screens in this navigator
return <HomeStack.Navigator
screenOptions={{
headerShown: false,
}}
>
<HomeStack.Screen
name="Home"
component={Home}
/>
<HomeStack.Screen
name="ScreenName"
component={ComponentToDisplayOnClick}
/>
<HomeStack.Screen
name="ScreenName"
component={ComponentToDisplayOnClick}
/>
</HomeStack.Navigator>
}
const LoggedInNavigator = () => (
<BottomStack.Navigator
screenOptions={() => ({
tabBarStyle: {
backgroundColor: '#1B1464',
height: 65,
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingBottom: 10,
paddingTop: 10
},
headerShown: false,
tabBarLabel: () => {return null}
})}
>
<BottomStack.Screen
name="HomeStack"
component={HomeStackScreen}
options={{
tabBarIcon: ({color}) => (
<View
style={styles.bottomNavCircle}
>
<MaterialCommunityIcons
name="home"
color={color}
size={30}
/>
</View>
)
}}
/>
... other bottom tabs
</BottomStack.Navigator>
)
const App: React.FC = () => {
return (
<NavigationContainer ref={navigationRef} >
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
<Stack.Screen
name="UnAuthenticated"
component={AuthNavigator}
/>
<Stack.Screen
name="Home"
component={LoggedInNavigator}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default App
Is there anything I'm doing wrong? I only want to navigate to a different screen on my home page, which is the first tab of the bottom navigator. Haven't seen any useful articles for this, all are showing stand alone use cases for navigators.
I started with React Native 12 days ago, from a Flutter background. Thanks
I solved this question by delaying the navigation call method invocation with ()=> arrow function. It navigates now, however, the bottom navigation bar still persists. Is there a way to hide the bottom bar on navigation? Thanks

Wrong back button behavior in react native

guys I have a question about navigation in react native.
So I mainly use TabNavigator. I have 2 main stack navigators in the app
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Profile" component={ProfileStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
In my ProfileStack screen, I have also two pages: MyProfile and UsersProfile:
const ProfileStack = createNativeStackNavigator();
function ProfileStackScreen({route, navigation}) {
return (
<ProfileStack.Navigator initialRouteName="MyProfile">
<ProfileStack.Screen name="MyProfile" component={MyProfilePage} />
<ProfileStack.Screen name="UserProfile" component={UserProfilePage} options={{
headerLeft: () => (<View>
<Button title="back" onPress={() => {navigation.goBack()}}/>
</View>)
}}/>
</ProfileStack.Navigator>
);
}
Now I want to navigate from the HomeScreen to the UserProfilePage and pass params to this screen. I'm doing it like this:
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen this</Text>
<Button
title="Go to another user profile"
onPress={() => navigation.navigate('Profile', {screen: 'UserProfile', params: {userId: 1235}})}
/>
</View>
);
}
So now, when I come to the page UserProfile I see that it loads also the Profile page, and just for a second I see blinking of ProfilePage and its UI that is not cool, and should it be like so? I guess not.
Then if I press the BACK button on UsersProfilePage, I'm navigating back to HomeScreen - and this is ok! This is what I expect!
But now, If I will press ProfileTab I see only UsersProfilePage but not MyProfilePage. When I press the BACK button again, I go back to the HomeScreen that is weird for me. Can u explain why it happens? Why I don't get back to the MyProfilePage.
I prepared an expo snack here. You can reproduce this behavior.
This is because you’re navigating to a screen in a nested navigator. It is ignoring the initial route. Then when you press the tab again it is still mounted and will still have the previous route state, which is just the screen without the initial screen.
By default, when you navigate a screen in the nested navigator, the specified screen is used as the initial screen and the initial route prop on the navigator is ignored. This behaviour is different from the React Navigation 4.
If you need to render the initial route specified in the navigator, you can disable the behaviour of using the specified screen as the initial screen by setting initial: false:
navigation.navigate('Root', {
screen: 'Settings',
initial: false,
});
See https://reactnavigation.org/docs/nesting-navigators/#rendering-initial-route-defined-in-the-navigator and https://reactnavigation.org/docs/navigation-lifecycle/

Expo Android there is a white flicker when switching from bottom tab navigator to material top tab navigator

White flicker when switching from bottom tab navigator to top tab navigator
This white flicker is much more noticeable outside of this gif. But I am using an Expo managed React Native project and when I switch from my Bottom tab navigator to my Top tab navigator the screen flickers white. This issue only occurs on Android. On top of that, when you press a TextInput to open the keyboard, the screen turns white in the section the keyboard takes up while the keyboard animation is occuring. Here are my navigators in App.js
const AuthTabs = createMaterialTopTabNavigator();
const AuthStackScreen = () => (
<AuthTabs.Navigator tabBarOptions={options}>
<AuthTabs.Screen name="Sign In" component={SignInScreen} />
<AuthTabs.Screen name="Sign Up" component={SignUpScreen} />
</AuthTabs.Navigator>
);
const Tab = createBottomTabNavigator();
const MainStack = () => (
<Tab.Navigator>
<Tab.Screen name="Deals" component={DealsStackScreen} />
<Tab.Screen name="Categories" component={CategoriesStackScreen} />
<Tab.Screen name="My Account" component={MyAccountStackScreen} />
</Tab.Navigator>
const RootStack = createStackNavigator();
const Root = () => (
<RootStack.Navigator headerMode="none" cardStyle={{opacity: 1}} >
<RootStack.Screen name="Home" component={MainStack}/>
<RootStack.Screen name="Auth" component={AuthStackScreen}/>
</RootStack.Navigator>
);
return (
<AuthContextProvider>
<NavigationContainer theme={{ colors: {background: `${Colors.surface}` }}}>
<Root />
</NavigationContainer>
</AuthContextProvider>
);
I tried adding my theme color to the NavigationContainer but this did not fix the issue. Also link shows the GIF of what is happening.
Yes, you have to wrap your RootStack around a View with backgroundColor as theme's backgroundColor
Your RootStack would look something like this now
import { useTheme } from '#react-navigation/native';
...
const { colors } = useTheme();
const RootStack = createStackNavigator();
const Root = () => (
<View style={{ flex:1, backgroundColor: colors.background }}> // This is the catch..Also it needs flex:1
<RootStack.Navigator headerMode="none" cardStyle={{ opacity: 1 }}>
<RootStack.Screen name="Home" component={MainStack} />
<RootStack.Screen name="Auth" component={AuthStackScreen} />
</RootStack.Navigator>
</View>
);

How do i go from one stack to another containing a tab stack in React Navigation 5.x?

So i got 4 different screen, a showcase screen, a loading screen, a home and a library screen
the showcase screen will be the initial screen here, so when i finish the showcase i go to the loading screen, after that to the home which contains two tabs both home and library
this is how i think it should be done, but is not working
const InitialStack = createStackNavigator();
const HomeStack = createStackNavigator();
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
function InitialStackScreen() {
return (
<InitialStack.Navigator>
<InitialStack.Screen name="Showcase" component={ShowcaseScreen} />
<InitialStack.Screen name="Loading" component={LoadingScreen} />
</InitialStack.Navigator>
);
}
function HomeStackScreen() {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Library" component={LibraryScreen} />
</HomeStack.Navigator>
);
}
export default function Navigation() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Showcase">
<Stack.Screen name="Showcase" component={InitialStackScreen} />
</Stack.Navigator>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
You don't have to initialise 3 different stack navigator constructors. Also, I believe the following way to nest the navigators will work for your use case, Nesting a root stack navigator with one stack navigator and one bottom tab navigator.
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
function InitialStackScreen() {
return (
<Stack.Navigator>
<InitialStack.Screen name="Showcase" component={ShowcaseScreen} />
<InitialStack.Screen name="Loading" component={LoadingScreen} />
</Stack.Navigator>
);
}
function HomeTabScreen() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Library" component={LibraryScreen} />
</Tab.Navigator>
);
}
export default function Navigation() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Showcase" component={InitialStackScreen} />
<Stack.Screen name="Home" component={HomeTabScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
More on nesting navigators and how they work here: https://reactnavigation.org/docs/nesting-navigators/
EDIT: To not be able to go back to loading and showcase screen
export default function Navigation() {
const isAuth = useSelector(state => state.isAuth) // some redux state that indicates if user is authenticated
return (
<NavigationContainer>
{!isAuth && <InitialStackScreen /> }
{isAuth && <HomeTabScreen />
</NavigationContainer>
);
}
It’s most likely because you don’t use createStackNavigator() of react-navigation
Also you use Stack.Navigator and Tab.Navigator, although you need to use one of these.
Check this snack!
https://snack.expo.io/#apollonseven/27cc9e

How to hide the header from Tab navigation (bottom-tabs) in react navigation 5.x?

i am trying to use createBottomTabNavigator function for create bottom navigation tab, i want to hide the
header, bellow the screenshot:
I have a BottomTabNavigator inside a stackNavigator bellow the code:
This is the rooter configuration file rooter.js
import React, { Component } from 'react';
import WelcomeScreen from '../component/WelcomeScreen';
import Login from '../component/login/Login';
import Register from '../component/register/Register';
import RegisterTwo from '../component/register/RegisterTwo';
import TabsBottom from '../component/tabs/TabsNavigation'
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
const AppSwitchNavigator = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="WelcomeScreen">
<Stack.Screen name="TabsBottom" component={TabsBottom} />
<Stack.Screen name="WelcomeScreen" component={WelcomeScreen} />
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="RegisterTwo" component={RegisterTwo} />
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
</NavigationContainer>
);
}
export const AppContainer = AppSwitchNavigator;
This is my nested navigator TabsNavigation.js
import React, { Component } from 'react';
import Explore from '../Explore';
import Settings from '../Settings';
import Profile from '../Profile';
import Search from '../Search';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/FontAwesome5';
import colors from '../../../styles/colors/index';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Explore') {
iconName = focused ? 'home': 'home';
color = focused ? colors.mainColor : colors.gray03;
} else if (route.name === 'Settings') {
iconName = focused ? 'cog' : 'cog';
color = focused ? colors.mainColor : colors.gray03;
}
else if (route.name === 'Search') {
iconName = focused ? 'search' : 'search';
color = focused ? colors.mainColor : colors.gray03;
}
else if (route.name === 'Profile') {
iconName = focused ? 'user-alt' : 'user-alt';
color = focused ? colors.mainColor : colors.gray03;
}
return <Icon name={iconName} size={30} color={color} />;
}
})}
tabBarOptions={{
activeTintColor: colors.mainColor,
inactiveTintColor: colors.gray03
}}
>
<Tab.Screen name="Explore" component={Explore} />
<Tab.Screen name="Search" component={Search} />
<Tab.Screen name="Profile" component={Profile} />
<Tab.Screen name="Settings" component={Settings} />
</Tab.Navigator>
);
}
export default function TabsBottom() {
return (
<MyTabs />
);
}
I want delete the screen's headres
Thanks for your help
From version 6.x.x
You just need to add
<Tab.Navigator screenOptions={{ headerShown: false }}>
or
<HomeStack.Navigator screenOptions={{ headerShown: false }}>
and it will hide the header
For the latest version in React Native:
If you want to remove the header for all bottom tabs, use this prompt:
<TabNavigator.Navigator screenOptions={{headerShown:false}}/>
Or, if you want to remove it for a particular bottomTabScreen, use this:
<TabNavigator.Screen name="home" component={HomeStack} />
Use following line. Write headerShown as false. It will remove header:
<Stack.Screen name="TabsBottom" options={{headerShown: false}} component={TabsBottom} />
To hide the 'Tabs Bottom' header you have to add a headerShown: false option to your TabsBottom Stack.Screen component like this:
const Stack = createStackNavigator();
const AppSwitchNavigator = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="WelcomeScreen">
<Stack.Screen name="TabsBottom" component={TabsBottom} options={{ headerShown: false }} />
<Stack.Screen name="WelcomeScreen" component={WelcomeScreen} />
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="RegisterTwo" component={RegisterTwo} />
<Stack.Screen name="Login" component={Login} />
</Stack.Navigator>
</NavigationContainer>
);
}
export const AppContainer = AppSwitchNavigator;
Use this syntax in bottomtab.js file
<Tab.Navigator screenOptions={{headerShown:false}}>
</Tab.Navigator>
(React Nav ver6.x) add this code snipet "options={{headerShown: false}}" in "<Tab.Screen />".It will delete header of each tab you add into.
I'm not really good at react-native stuff but the documentation about hiding tab bar
says that, in nested navigator (tabNavigator inside stackNavigator in the doc), you have to put your screen in the parent navigator, which make sense since each navigator handle their own screen.
If I refer to your screen, you have a stackNavigator and a tabNavigator, so just apply this principle. If you still need help, please provide a repro (A Snack expo would be appreciated, or just paste your full code in your question) so we can work on it.

Categories