React Native Bottom tab bar jump on every load - reactjs

i have the exact same problem like on issue:
React Native header / bottom tabbar jumping on first app load
On every load the bottom bar jumps up and down for unknown reason. I wrapped the root app in SafeAreaProvider, i wrapped my screens in SafeAreaView and still the same thing happens.
Here is my code:
Root App:
const App = () => {
return (
<SafeAreaProvider>
<StatusBar backgroundColor="#01497C" />
<NavigationContainer>
<Stack.Navigator
initialRouteName="AuthLoadingScreen"
screenOptions={{headerShown: false}}>
<Stack.Screen
name="AuthLoadingScreen"
component={AuthLoadingScreen}
/>
<Stack.Screen name="Home" component={Tabs} />
<Stack.Screen name="QuizScreen" component={QuizScreen} />
<Stack.Screen name="QuizReviewScreen" component={QuizReviewScreen} />
<Stack.Screen name="QuizEndScreen" component={QuizEndScreen} />
</Stack.Navigator>
</NavigationContainer>
</SafeAreaProvider>
);
};
Tabs:
const Tabs = () => {
const TabBarCustom = ({children, onPress}) => {
return (
<TouchableOpacity
style={{top: -10, justifyContent: 'center', alignItems: 'center'}}
onPress={onPress}
activeOpacity={1}>
<LinearGradient
style={{
width: 70,
height: 70,
borderRadius: 35,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
}}
colors={['#01497C', '#89C2D9']}>
{children}
</LinearGradient>
</TouchableOpacity>
);
};
return (
<Tab.Navigator
tabBarOptions={{
showLabel: false,
style: {
height: 60,
},
}}>
<Tab.Screen
name="Quizzes"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="apps-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Quizzes
</Text>
</View>
),
}}
/>
<Tab.Screen
name="Flashcards"
component={FlashCardsScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="copy-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Flashcards
</Text>
</View>
),
}}
/>
<Tab.Screen
name="Import"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Icon
name="plus"
color={focused ? '#A9D6E5' : 'white'}
size={42}
/>
</View>
),
tabBarButton: props => <TabBarCustom {...props} />,
}}
/>
<Tab.Screen
name="Account"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="person-outline"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Account
</Text>
</View>
),
}}
/>
<Tab.Screen
name="About"
component={QuizzesScreen}
options={{
tabBarIcon: ({focused}) => (
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<Ionicon
name="search"
color={focused ? '#89C2D9' : '#2A6F97'}
size={30}
/>
<Text
style={{color: focused ? '#89C2D9' : '#2A6F97', fontSize: 13}}>
Search
</Text>
</View>
),
}}
/>
</Tab.Navigator>
);
};
The issue happens every time tabs get loaded.

I had the same issue, in my case I was using Custom StatusBar in different screens with different props. The issue was I wasn't using translucent prop in all screen StatusBar. Using translucent in all screen StatusBar fixed the problem. Give me a thumbs up if it solve your problem.

I use MaterialCommunityIcons for tab icons so,
I sove this issue with
useLayoutEffect(() => {
async function loadIcons() {
setIsLoading(true);
await MaterialCommunityIcons.loadFont();
setIsLoading(false);
}
loadIcons();
}, []);
if (isLoading) {
return <></>;
}
Why useLayouEffect?
The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint. read more

Related

How to manage nested navigations so that Homepage displays Navbar when signed in?

I have two navigators and the idea is to have the main navigation container to hold the general pages: Home, SignIn, SignUp, confirmEmail and NewPassword but once the user login in to Home I would like the navigation bar to display and have its own navigation routings.
Navigation.js:
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
{user ? (
<Stack.Screen name="HomeScreen" component={HomeScreen} />
) : (
<>
<Stack.Screen name="SignIn" component={SignInScreen} />
<Stack.Screen name="SignUp" component={SignUpScreen} />
<Stack.Screen name="ConfirmEmail" component={ConfirmEmailScreen} />
<Stack.Screen
name="ResetPassword"
component={ResetPasswordScreen}
/>
<Stack.Screen name="NewPassword" component={NewPasswordScreen} />
</>
)}
</Stack.Navigator>
</NavigationContainer>
Navbar.js
const Navbar = () => {
const tabOffsetValue = useRef(new Animated.Value(0)).current;
return (
// <NavigationContainer>
<Tab.Navigator
screenOptions={{
tabBarShowLabel: false,
headerShown: false,
// Floating Tab Bar...
tabBarStyle: {
backgroundColor: 'white',
position: 'absolute',
// Max Height...
borderRadius: 10,
// Shadow...
},
}}>
{
// Tab Screens....
// Tab ICons....
}
<Tab.Screen
name={'Home'}
component={HomeScreen}
options={{
tabBarIcon: ({focused}) => (
<View
style={{
// centring Tab Button...
position: 'absolute',
top: 20,
}}>
<Icon
name="home"
size={20}
color={focused ? 'red' : 'gray'}></Icon>
</View>
),
}}
listeners={({navigation, route}) => ({
// Onpress Update....
tabPress: e => {
Animated.spring(tabOffsetValue, {
toValue: 0,
useNativeDriver: true,
}).start();
},
})}>
</Tab.Screen>
HomeScreen.Js
const HomeScreen = () => {
const signOut = () => {
Auth.signOut();
};
return (
<View>
<Navbar/>
<Text style={{fontSize: 24, alignSelf: 'center'}}>Welcome to Flimpi</Text>
<Text
onPress={signOut}
style={{
width: '100%',
textAlign: 'center',
color: 'red',
marginTop: 'auto',
marginVertical: 20,
fontSize: 20
}}>
Sign Out!
</Text>
</View>
);
};
Expectedly I am getting the following error:
Require cycle: src/screens/HomeScreen/index.js -> src/components/Navbar/index.js -> src/components/Navbar/Navbar.js -> src/screens/HomeScreen/index.js
Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle.
The Error makes sense but I just do not know how to structure the code

React Navigation / Native flickers when use custom header component

When I change screens with react-native-navigation I have a flicker of underlying background on ios, when I change screens with standard navigation everything is going smooth but with the custom one it look like it applies background color too late, is there some prop I should be aware of when dealing with custom header bar?
this is the code of custom header:
export const CustomNavigation = (props: NativeStackHeaderProps) => {
const styles = useStyleSheet(themedStyles);
return (
<SafeAreaView style={styles.wrapper}>
<Pressable onPress={props.navigation.goBack}>
<ArrowLeftIcon />
</Pressable>
<Text>{props.options.title}</Text>
<Pressable>
<NavMenuIcon />
</Pressable>
</SafeAreaView>
);
};
const themedStyles = StyleService.create({
wrapper: {
height: Platform.OS === "ios" ? 100 : 70,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: spacing.regular,
transform: Platform.OS === "ios" ? [{ translateY: 20 }] : [],
backgroundColor: "#fff",
},
});
app.tsx
const Stack = createNativeStackNavigator<RootStackParamList>();
return (
<SafeAreaProvider onLayout={onLayoutRootView}>
<NavigationContainer>
<ApplicationProvider {...eva} theme={{ ...eva.light, ...theme }}>
<ReduxProvider store={store}>
<Stack.Navigator
initialRouteName="Home"
screenOptions={{
header: (props) => <CustomNavigation {...props} />,
}}
>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Scheduler"
component={ScheduleScreen}
options={{
title: "Plan your booking",
}}
/>
<Stack.Screen
name="LocationPicker"
component={PickLocationScreen}
/>
</Stack.Navigator>
</ReduxProvider>
</ApplicationProvider>
</NavigationContainer>
</SafeAreaProvider>
On android it looks ok, there is no background flash, only on ios. Thanks for any suggestions.

A View is partially hidden after wrapped by TouchableOpacity

I'm making a tabNavigator with a tabScreen like this:
<Tab.Screen
name="ListingEdit"
component={ListingEditScreen}
options={({navigation}) => ({
tabBarButton: () => (
<NewListButton
onPress={() => navigation.navigate('ListingEdit')}></NewListButton>
),
tabBarIcon: ({size, color}) => (
<MaterialCommunityIcons
name="plus-circle"
size={size}
color={color}></MaterialCommunityIcons>
),
})}
/>
and NewListButton component:
<View style={styles.container}>
<MaterialCommunityIcons name="plus-circle" color={colors.white} size={25} />
</View>
Everything looks good, but after wrapping NewListButton with a TouchableOpacity
<TouchableOpacity onPress={onPress}>
<View style={styles.container}>
<MaterialCommunityIcons name="plus-circle" color={colors.white} size={25} />
</View>
</TouchableOpacity>
the NewListButton component is partially hidden like this
I tried adding the zIndex but it didn't work. Is there anyone had the same problem before, I hope your help, thanks so much !
My container style:
const styles = StyleSheet.create({
container: {
backgroundColor: colors.primary,
borderRadius: 35,
height: 70,
width: 70,
bottom: 30,
borderColor: colors.white,
borderWidth: 10,
alignItems: 'center',
justifyContent: 'center'
}
});
Have you tried to put the TouchableOpacity inside the View?
<View style={styles.container}>
<TouchableOpacity onPress={onPress}>
<MaterialCommunityIcons name="plus-circle" color={colors.white}
size={25}></MaterialCommunityIcons>
</TouchableOpacity>
</View>
or try to add the {styles.container} to TouchableOpacity

not able to logging out from the app in react native?

i am working on a react native project using redux. i have one stack navigator and one drawer navigator.
i am not able to logout from the app. i want to change store value while logging out. when i am dispatching the action from the logout onPress. it throws error: props.dispatch is not a function. how do i call. i tried many ways it always throwing an error. and how to set all reducers value to intial state while logout? Thank you in advance
App.js
<RootStack.Navigator screenOptions={{
headerShown: false
}}>
{/* <StatusBar backgroundColor={isLoading ? '#000000' : '#F3F3F3'} /> */}
{this.props.data.splashScreen.loading ?
(<RootStack.Screen name={'SplashScreen'} component={SplashScreen} />) :
this.props.data.login.isAuthorized ?
(<RootStack.Screen name="MainNavigator" component={MainNavigator} />)
:
(
<RootStack.Screen name="Login" component={MainStack} />)}
</RootStack.Navigator>
splashScreen and login are reducer store value
MainNavigator.js
const GradientHeader = (props) => (
<View style={{ backgroundColor: "transparent" }}>
<LinearGradient
colors={["#6CCFF6", "#596AB2"]}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
style={
{
/* height: 128 */
/* height: Header.HEIGHT */
}
}
>
<Header {...props} />
</LinearGradient>
</View>
);
const DashboardStackScreen = ({ navigation }) => {
return (
<DashboardStack.Navigator
screenOptions={{
headerTitle: "Good Morning, John",
header: (props) => <GradientHeader {...props} />,
headerLeft: () => (
<TouchableOpacity onPress={navigation.openDrawer} style={{ padding: 20 }}>
<Image source={require("../assets/images/menu_bar.png")} style={{ width: 18, height: 12 }} />
</TouchableOpacity>
),
headerTransparent: true,
headerStyle: {
backgroundColor: "transparent",
},
headerTintColor: "#fff",
headerTitleStyle: { fontFamily: "OpenSans-SemiBold", fontSize: 20 },
}}
>
<DashboardStack.Screen name="Dashboard" component={Dashboard} />
</DashboardStack.Navigator>
);
};
export default ({ navigation }) => {
return (
<Drawer.Navigator
initialRouteName="Dashboard"
drawerContent={(props) => <DrawerContent {...props} />}
hideStatusBar={false}
focused={true}
labelStyle={{ fontSize: 14, fontFamily: "OpenSans-SemiBold" }}
drawerContentOptions={{ activeBackgroundColor: "#F1F1F1", activeTintColor: "#000000", inactiveTintColor: "#818181", itemStyle: { marginLeft: 0, paddingHorizontal: 10, width: "100%", borderRadius: 0 } }}
>
<Drawer.Screen
name="Dashboard"
component={DashboardStackScreen}
options={{
drawerIcon: ({ focused, size }) => <Image source={require("../assets/images/dashboard.png")} style={{ height: 17.78, width: 16 }} resizeMode="contain" />,
}}
/>
<Drawer.Screen
name="My Profile"
component={MyProfileStackScreen}
options={{
drawerIcon: ({ focused, size }) => <Image source={require("../assets/images/profile.png")} style={{ height: 16, width: 16 }} resizeMode="contain" />,
}}
/>
</Drawer.Navigator>
);
};
DrawerContent.js
import { resetData } from "../Storage/Storage";
export function DrawerContent(props) {
return (
<SafeAreaView style={styles.baseContainer}>
<KeyboardAvoidingView behaviour="padding" style={styles.baseContainer}>
<TouchableWithoutFeedback style={styles.baseContainer} onPress={Keyboard.dismiss}>
<View style={styles.baseContainer}>
<TouchableOpacity
style={{ flex: 2, alignItems: "center", justifyContent: "center" }}
onPress={() => {
props.navigation.navigate("Dashboard");
}}
>
<Image source={require("../assets/images/MJB_Logo.png")} style={{ width: 197, height: 59 }} />
</TouchableOpacity>
<View style={{ flex: 5 }}>
<DrawerContentScrollView {...props}>
<DrawerItemList {...props} />
<DrawerItem
labelStyle={{ fontSize: 14, fontFamily: "OpenSans-SemiBold" }}
activeBackgroundColor="#F1F1F1"
activeTintColor="#000000"
inactiveTintColor="#818181"
label="Logout"
icon={({ focused, color, size }) => {
return <Image source={require("../assets/images/logout.png")} style={{ height: 14.36, width: 14.36 }} resizeMode="contain" />;
}}
onPress={() => resetData()}
/>
</DrawerContentScrollView>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</SafeAreaView>
);
}
Storage.js
export const resetData = async () => {
try {
//await AsyncStorage.removeItem('isRemembered')
await AsyncStorage.removeItem("userDetails");
} catch (e) {
// saving error
}
};

React Navigation: passing parameters to a route: TyperError

I have a list of profiles on my Screen "NerdList" built using ListItems (react-native-element) and a Flatlist. When you click on a profile from the list, the app should navigate to the "Profile" screen and pass a test parameter with it.
NerdList Screen:
import React from "react";
import { withNavigation } from '#react-navigation/compat';
import { StyleSheet, FlatList} from "react-native";
import { ListItem } from "react-native-elements";
import nerdProfiles from '../constants/nerdProfiles';
import { Block, Text } from 'galio-framework';
import argonTheme from "../constants/Theme";
import { TouchableOpacity } from "react-native-gesture-handler";
class NerdList extends React.Component {
renderItem = ({item}) => (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Profile', {test: 'Hello'})}
>
<ListItem
title={
<Block>
<Text style={styles.names}>
{item.name}
</Text>
</Block>
}
subtitle={
<Block>
<Text style={styles.descriptions}>
{item.shortDescription}
</Text>
</Block>
}
leftAvatar={{ source: { uri: item.image } }}
bottomDivider
chevron
/>
</TouchableOpacity>
);
render() {
return (
<FlatList
data={nerdProfiles.bios}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
);
};
};
export default withNavigation(NerdList);
The navigation alone works, but when I try to pass a parameter, I receive a TypeError: undefined is not an object (evaluating '_ref3.route').
Here is the code I am using to receive the route on the "Profile" screen:
const {test} = route.params;
Full Profile Screen Code:
import React from "react";
import {
StyleSheet,
Dimensions,
ScrollView,
Image,
ImageBackground,
Platform
} from "react-native";
import { Block, Text, theme } from "galio-framework";
import { Button } from "../components";
import { Images, argonTheme } from "../constants";
import { HeaderHeight } from "../constants/utils";
import { FlatList, TouchableWithoutFeedback } from "react-native-gesture-handler";
import nerdProfiles from "../constants/nerdProfiles";
import ArticleCard from "../components/ArticleCard";
import VideoCard from "../components/VideoCard";
const { width, height } = Dimensions.get("screen");
const thumbMeasure = (width - 48 - 32) / 3;
//keyExtractor = (item, index) => index.toString()
class Profile extends React.Component {
renderVideoItem = ({item}) => {
return(
<Block style={{ marginRight: theme.SIZES.BASE }}>
<TouchableWithoutFeedback>
<VideoCard
item={item}
imageStyle={{ width: "auto", height: 94 }}
style={{ width: width / 3.75}}
/>
</TouchableWithoutFeedback>
</Block>
);
};
renderArticleItem = ({item}) => {
return(
<Block style={{ marginRight: theme.SIZES.BASE }}>
<TouchableWithoutFeedback>
<ArticleCard
item={item}
imageStyle={{ width: "auto", height: 94 }}
style={{ width: width / 3.75}}
/>
</TouchableWithoutFeedback>
</Block>
);
};
render() {
const { params } = this.props.navigation.state;
const test= params ? params.test: null;
return (
<Block flex style={styles.profile}>
<Block flex>
<ImageBackground
source={Images.ProfileBackground}
style={styles.profileContainer}
imageStyle={styles.profileBackground}
>
<ScrollView
showsVerticalScrollIndicator={false}
style={{ width, marginTop: "25%" }}
>
<Block flex style={styles.profileCard}>
<Block middle style={styles.avatarContainer}>
<Image
source={{uri: nerdProfiles.bios[0].image}}
style={styles.avatar}
/>
</Block>
<Block style={styles.info}>
<Block
middle
row
space="evenly"
style={{ marginTop: 20, paddingBottom: 24 }}
>
<Button
small
style={{ backgroundColor: argonTheme.COLORS.DEFAULT }}
>
FOLLOW
</Button>
</Block>
<Block row space="between">
<Block middle>
<Text
size={18}
color="#525F7F"
style={{ marginBottom: 4, fontFamily: 'open-sans-bold' }}
>
2K
</Text>
<Text style={{ fontFamily: 'open-sans-regular' }} size={12} color={argonTheme.COLORS.TEXT}>Followers</Text>
</Block>
<Block middle>
<Text
color="#525F7F"
size={18}
style={{ marginBottom: 4, fontFamily: 'open-sans-bold' }}
>
10
</Text>
{test}
<Text style={{ fontFamily: 'open-sans-regular' }} size={12} color={argonTheme.COLORS.TEXT}>Content</Text>
</Block>
</Block>
</Block>
<Block flex>
<Block middle style={styles.nameInfo}>
<Text style={{ fontFamily: 'open-sans-regular' }} size={28} color="#32325D">
{test}
</Text>
<Text size={16} color="#32325D" style={{ marginTop: 10, fontFamily: 'open-sans-light' }}>
{nerdProfiles.bios[0].location}
</Text>
</Block>
<Block style={styles.categories}>
<Button small>Math</Button>
<Button small>Finance</Button>
<Button small>Physics</Button>
</Block>
<Block middle style={{ marginTop: 30, marginBottom: 16 }}>
<Block style={styles.divider} />
</Block>
<Block middle>
<Text
size={16}
color="#525F7F"
style={{ textAlign: "center", fontFamily: 'open-sans-regular' }}
>
{nerdProfiles.bios[0].longDescription}
</Text>
<Button
color="transparent"
textStyle={{
color: "#233DD2",
fontWeight: "500",
fontSize: 16,
fontFamily: 'open-sans-regular'
}}
>
Show more
</Button>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Video Appearances
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block style={{ marginHorizontal: theme.SIZES.BASE }}>
<FlatList
style={styles.flatlist}
keyExtractor={this.keyExtractor}
data={nerdProfiles.bios[0].videos}
renderItem={this.renderVideoItem}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Articles Written
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block style={{ marginHorizontal: theme.SIZES.BASE }}>
<FlatList
style={styles.flatlist}
keyExtractor={this.keyExtractor}
data={nerdProfiles.bios[0].articles}
renderItem={this.renderArticleItem}
horizontal={true}
showsHorizontalScrollIndicator={false}
/>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Podcast Appearances
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Live Appearances
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
<Block
row
style={{ paddingVertical: 14 }}
space="between"
>
<Text bold size={16} color="#525F7F" style={{ marginTop: 3 }}>
Academic Work
</Text>
<Button
small
color="transparent"
textStyle={{ color: "#5E72E4", fontSize: 14 }}
>
View all
</Button>
</Block>
</Block>
</Block>
<Block style={{ marginBottom: 25 }}/>
</ScrollView>
</ImageBackground>
</Block>
</Block>
);
}
}
NerdList screen (first screen)
import React from "react";
import { Dimensions } from "react-native";
import { createStackNavigator } from "#react-navigation/stack";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
// screens
import Feed from "../screens/Feed";
// import Onboarding from "../screens/Onboarding";
import Pro from "../screens/Pro";
import Profile from "../screens/Profile";
import Register from "../screens/Register";
import Elements from "../screens/Elements";
import Articles from "../screens/Articles";
import Search from "../screens/Search";
import Cart from "../screens/Cart";
import NerdList from "../screens/NerdList";
// settings
import SettingsScreen from "../screens/Settings";
import AgreementScreen from "../screens/Agreement";
import PrivacyScreen from "../screens/Privacy";
import AboutScreen from "../screens/About";
import NotificationsScreen from "../screens/Notifications";
// Notifications
import PersonalNotifications from "../screens/PersonalNotifications";
import SystemNotifications from "../screens/SystemNotifications";
// drawer
import CustomDrawerContent from "./Menu";
// header for screens
import { Icon, Header } from "../components";
import { argonTheme, tabs } from "../constants";
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
const { width } = Dimensions.get("screen");
export const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const Tab = createBottomTabNavigator();
function NotificationsStack() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color }) => {
let iconName;
if (route.name === "Personal") {
iconName = "user";
} else if (route.name === "System") {
iconName = "database";
} else if (route.name === "NerdList") {
iconName = "user"
}
// You can return any component that you like here!
return (
<Icon
name={iconName}
family="entypo"
size={22}
color={color}
style={{ marginTop: 10 }}
/>
);
}
})}
tabBarOptions={{
activeTintColor: argonTheme.COLORS.PRIMARY,
inactiveTintColor: "gray",
labelStyle: {
fontFamily: "open-sans-regular"
}
}}
>
<Tab.Screen name="Personal" component={PersonalNotifications} navigation />
<Tab.Screen name="System" component={SystemNotifications} />
<Tab.Screen name="NerdList" component={NerdList} />
</Tab.Navigator>
);
}
function BottomTabStack() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ color }) => {
let iconName;
if (route.name === "Feed") {
iconName = "user";
} else if (route.name === "System") {
iconName = "database";
} else if (route.name === "NerdList") {
iconName = "user"
}
// You can return any component that you like here!
return (
<Icon
name={iconName}
family="entypo"
size={22}
color={color}
style={{ marginTop: 10 }}
/>
);
}
})}
tabBarOptions={{
activeTintColor: argonTheme.COLORS.PRIMARY,
inactiveTintColor: "gray",
labelStyle: {
fontFamily: "open-sans-regular"
}
}}
>
<Tab.Screen name="Feed" component={Feed} />
<Tab.Screen name="System" component={SystemNotifications} />
<Tab.Screen name="NerdList" component={NerdList} />
</Tab.Navigator>
);
}
function ElementsStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Elements"
component={Elements}
options={{
header: ({ navigation, scene }) => (
<Header title="Elements" navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function NerdListStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="NerdList"
component={NerdList}
options={{
header: ({ navigation, scene }) => (
<Header title="NerdList" navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Profile"
component={Profile}
options={{
header: ({ navigation, scene }) => (
<Header
transparent
white
title="Profile"
navigation={navigation}
scene={scene}
back={true}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" },
headerTransparent: true
}}
/>
</Stack.Navigator>
);
}
function SettingsStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Settings"
component={SettingsScreen}
options={{
header: ({ navigation, scene }) => (
<Header title="Settings" scene={scene} navigation={navigation} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Agreement"
component={AgreementScreen}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Agreement"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Privacy"
component={PrivacyScreen}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Privacy"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="About"
component={AboutScreen}
options={{
header: ({ navigation, scene }) => (
<Header back title="About" scene={scene} navigation={navigation} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="NotificationsSettings"
component={NotificationsScreen}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Notifications"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Cart"
component={Cart}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Shopping Cart"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Notifications"
component={NotificationsStack}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Notifications"
scene={scene}
navigation={navigation}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function ArticlesStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Articles"
component={Articles}
options={{
header: ({ navigation, scene }) => (
<Header title="Articles" navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function ProfileStack() {
return (
<Stack.Navigator initialRouteName="Profile" mode="card" headerMode="screen">
<Stack.Screen
name="Profile"
component={Profile}
options={{
header: ({ navigation, scene }) => (
<Header
transparent
white
title="Profile"
navigation={navigation}
scene={scene}
back={true}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" },
headerTransparent: true
}}
/>
<Stack.Screen
name="Cart"
component={Cart}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Shopping Cart"
navigation={navigation}
scene={scene}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" }
}}
/>
<Stack.Screen
name="Notifications"
component={NotificationsStack}
options={{
header: ({ navigation, scene }) => (
<Header
back
title="Notifications"
navigation={navigation}
scene={scene}
/>
),
cardStyle: { backgroundColor: "#FFFFFF" }
}}
/>
</Stack.Navigator>
);
}
function FeedStack() {
return (
<Stack.Navigator mode="card" headerMode="screen">
<Stack.Screen
name="Feed"
component={BottomTabStack}
options={{
header: ({ navigation, scene }) => (
<Header
title="Feed"
navigation={navigation}
scene={scene}
/>
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
<Stack.Screen
name="Search"
component={Search}
options={{
header: ({ navigation, scene }) => (
<Header title="Search" back navigation={navigation} scene={scene} />
),
cardStyle: { backgroundColor: "#F8F9FE" }
}}
/>
</Stack.Navigator>
);
}
function AppStack() {
return (
<Drawer.Navigator
style={{ flex: 1 }}
drawerContent={props => <CustomDrawerContent {...props} />}
drawerStyle={{
backgroundColor: "white",
width: width * 0.8
}}
drawerContentOptions={{
activeTintcolor: "white",
inactiveTintColor: "#000",
activeBackgroundColor: "transparent",
itemStyle: {
width: width * 0.75,
backgroundColor: "transparent",
paddingVertical: 16,
paddingHorizonal: 12,
justifyContent: "center",
alignContent: "center",
alignItems: "center",
overflow: "hidden"
},
labelStyle: {
fontSize: 18,
marginLeft: 12,
fontWeight: "normal"
}
}}
initialRouteName="Feed"
>
<Drawer.Screen name="Feed" component={FeedStack} />
<Drawer.Screen name="Profile" component={ProfileStack} />
<Drawer.Screen name="Account" component={Register} />
<Drawer.Screen name="Elements" component={ElementsStack} />
<Drawer.Screen name="Articles" component={ArticlesStack} />
<Drawer.Screen name="Settings" component={SettingsStack} />
<Drawer.Screen name="NerdList" component={NerdListStack} />
</Drawer.Navigator>
);
}
export default function OnboardingStack() {
return (
<Stack.Navigator mode="card" headerMode="none">
<Stack.Screen
name="Onboarding"
component={Pro}
option={{
headerTransparent: true
}}
/>
<Stack.Screen name="App" component={AppStack} />
</Stack.Navigator>
);
}
As #satya164 pointed out in a comment here, the problem was that I was passing a param to a nested navigator incorrectly. I was attempting to pass the param with:
onPress={() => this.props.navigation.navigate('Profile', {test: 'Hello'})}
The correct way to pass a param to a nested navigator is:
onPress={() => this.props.navigation.navigate('Profile', {screen: 'Profile', params: {test: 'name'}})}

Resources