I am facing some weird behaviour with react navigation version 6.
When I have a headerLeft property assigned my headerTitleStyle doesn't work anymore.
So if I assign some value to headerLeft to place an icon let's say, my headerTitleStyle is not applying styles to the title, which is really weird.
home.navigator.js
import React from "react";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import { ProductsScreen } from "../screens/products.screen";
import { colors } from "../theme/colors";
import { fonts } from "../theme/fonts";
import { MenuIcon } from "../components/menu-icon.component";
import { TouchableOpacity } from "react-native";
const Stack = createNativeStackNavigator();
export const HomeNavigator = () => {
return (
<Stack.Navigator
initialRouteName="Products"
screenOptions={{
headerTitleStyle: { <<//Doesn't work when headerLeft is assigned.
fontFamily: fonts.black,
},
headerStyle: {
backgroundColor: colors.bg.secondary,
color:colors.brand.secondary,
},
headerLeft: () => (
<TouchableOpacity>
<MenuIcon height={52} width={52} weight={1.5} color={colors.brand.secondary} />
</TouchableOpacity>
),
}}
>
<Stack.Screen
options={{ title: "Marketplace", headerShadowVisible: false }}
name="Products"
component={ProductsScreen}
/>
</Stack.Navigator>
);
};
app.navigator.js:
import React from "react";
import { createMaterialBottomTabNavigator } from "#react-navigation/material-bottom-tabs";
import { Ionicons } from "#expo/vector-icons";
import { colors } from "../theme/colors";
import { fonts } from "../theme/fonts";
import { Text } from "react-native";
import { HomeNavigator } from "./home.navigator";
import { CartScreen } from "../screens/cart.screen";
import { SearchScreen } from "../screens/search.screen";
const Tab = createMaterialBottomTabNavigator();
export const AppNavigator = () => (
<Tab.Navigator
initialRouteName="Products"
shifting={true}
screenOptions={({ route }) => ({
tabBarLabel: (
<Text style={{ fontFamily: fonts.bold, textAlign: "center" }}>
{route.name}
</Text>
),
tabBarIcon: ({ focused, color }) => {
let iconName;
if (route.name === "Products") {
iconName = focused ? "home-sharp" : "home-outline";
} else if (route.name === "Search") {
iconName = focused ? "search" : "search-outline";
} else {
iconName = focused ? "cart" : "cart-outline";
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={20} color={color} />;
},
})}
barStyle={{
backgroundColor: colors.bg.secondary,
fontFamily: fonts.regular,
}}
activeColor={colors.brand.secondary}
inactiveColor="gray"
>
<Tab.Screen name="Products" component={HomeNavigator} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Cart" component={CartScreen} />
</Tab.Navigator>
);
Thanks in advance!
Related
Why does this error appear? whereas in the previous version of react native it worked 0.66.4, API 29 with openjdk8. I don't know, I've tried using the previous version but a rendering error appears.
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: number.
Check the render method of Icon.
TabItem.js
import React from 'react'
import { StyleSheet, Text, TouchableOpacity } from 'react-native'
import { IconAbout, IconAboutActive, IconHome, IconHomeActive, IconNearby, IconNearbyActive} from '../../assets'
import { WARNA_UTAMA, WARNA_DISABLE } from '../../utils/constant'
const TabItem = ({ isFocused, onPress, onLongPress, label }) => {
const Icon = () => {
if (label === 'Home') return isFocused ? <IconHomeActive /> : <IconHome />
if (label === 'Nearby') return isFocused ? <IconNearbyActive /> : <IconNearby />
if (label === 'About') return isFocused ? <IconAboutActive /> : <IconAbout />
return <IconHome />
}
return (
<TouchableOpacity
onPress={onPress}
onLongPress={onLongPress}
style={styles.container}>
<Icon />
<Text style={styles.text(isFocused)}>
{label}
</Text>
</TouchableOpacity>
)
}
export default TabItem
const styles = StyleSheet.create({
container:{
alignItems: 'center',
},
text: (isFocused) => ({
fontSize: 13,
color: isFocused ? WARNA_UTAMA : WARNA_DISABLE,
})
})
BottomNavigator.js
import React from 'react'
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native'
import TabItem from '../TabItem';
const BottomNavigator = ({ state, descriptors, navigation }) => {
const focusedOptions = descriptors[state.routes[state.index].key].options;
if (focusedOptions.tabBarVisible === false) {
return null;
}
return (
<View style={ styles.container }>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
return (
<TabItem
key={index}
label={label}
isFocused={isFocused}
onPress={onPress}
onLongPress={onLongPress}
/>
);
})}
</View>
);
}
export default BottomNavigator
const styles = StyleSheet.create({
container:{
flexDirection: 'row',
backgroundColor: '#FFFF',
justifyContent: 'space-between',
paddingHorizontal: 48,
paddingVertical: 8,
borderRadius: 50,
}
})
Route.js
import React from 'react';
import {StyleSheet} from 'react-native';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {About, Home, Nearby, Splash} from '../pages';
import {BottomNavigator} from '../components';
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const MainApp = () => {
return (
{
<Tab.Navigator tabBar={props => <BottomNavigator {...props} />}>
<Tab.Screen
name="Home"
component={Home}
options={{headerShown: false}}
/>
<Tab.Screen
name="Nearby"
component={Nearby}
options={{headerShown: false}}
/>
<Tab.Screen
name="About"
component={About}
options={{headerShown: false}}
/>
</Tab.Navigator>
}
);
};
const Router = () => {
return (
<Stack.Navigator initialRouteName="Splash">
<Stack.Screen
name="Splash"
component={Splash}
options={{headerShown: false}}
/>
<Stack.Screen
name="MainApp"
component={MainApp}
options={{headerShown: false}}
/>
</Stack.Navigator>
);
};
export default Router;
const styles = StyleSheet.create({});
This code, should can be rendered custom local icon correctly
Would anyone be able to give me help regarding React Navigation with Expo? The issue is with the drawer component where the 'Hamburger' icon isn't opening or closing the component when a user presses the icon. However, it does open/close on a default swipe gesture from React Navigation. Please see below for my code:
Router:
import React from 'react';
import { NavigationContainer, DrawerActions } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { IconButton } from 'react-native-paper'
import i18n from '../i18n/i18n';
//Theme
import Theme from '../theme/theme'
//Components
import Menu from '../components/Menu'
//Import Interfaces
import { RootDrawerParamList } from '../utils/typescript/type.d';
import { IProps } from '../utils/typescript/props.d';
//Import Screens
import Screen1 from '../screens/Screen1';
import Screen2 from '../screens/Screen2';
import SettingsScreen from '../screens/Settings';
const Drawer = createDrawerNavigator<RootDrawerParamList>();
export default class Router extends React.Component<IProps, any> {
constructor(props: IProps) {
super(props);
}
render() {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName='Screen1'
drawerContent={(props: any) => <Menu {...props} />}
screenOptions={({
swipeEnabled: true
})}>
<Drawer.Screen
name="Screen1"
component={Screen1}
initialParams={{ i18n: i18n, Theme: Theme }}
options={({route, navigation} : any) => ({
headerRight: () => (<IconButton icon="cog" size={24} color={Theme.colors.text} onPress={() => navigation.navigate('Settings')} />),
route: {route},
navigation: {navigation}
})}
/>
<Drawer.Screen
name="Settings"
component={SettingsScreen}
initialParams={{ i18n: i18n, Theme: Theme }}
options={({route, navigation} : any) => ({
headerTitle: i18n.t('settings', 'Settings'),
headerLeft: () => (<IconButton icon="arrow-left" color={Theme.colors.text} size={24} onPress={() => navigation.goBack()} />),
route: {route},
navigation: {navigation}
})}
/>
<Drawer.Screen
name="Screen2"
component={Screen2}
initialParams={{ i18n: i18n, Theme: Theme }}
options={({route, navigation} : any) => ({
route: {route},
navigation: {navigation}
})}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
}
Menu
import React from 'react';
import { FlatList, StyleSheet, View } from 'react-native';
import { List, Title } from 'react-native-paper';
import { getDefaultHeaderHeight } from '#react-navigation/elements';
import { DrawerItem } from '#react-navigation/drawer';
import { useSafeAreaFrame, useSafeAreaInsets } from 'react-native-safe-area-context';
//Import Interfaces
import { IListItem } from '../utils/typescript/types.d';
import { IPropsMenu } from '../utils/typescript/props.d';
import { IStateMenu } from '../utils/typescript/state.d';
//A function is used to pass the header height, using hooks.
function withHeightHook(Component: any){
return function WrappedComponent(props: IPropsMenu) {
/*
Returns the frame of the nearest provider. This can be used as an alternative to the Dimensions module.
*/
const frame = useSafeAreaFrame();
/*
Returns the safe area insets of the nearest provider. This allows manipulating the inset values from JavaScript. Note that insets are not updated synchronously so it might cause a slight delay for example when rotating the screen.
*/
const insets = useSafeAreaInsets();
return <Component {...props} headerHeight={getDefaultHeaderHeight(frame, false, insets.top)} />
}
}
class Menu extends React.Component<IPropsMenu, IStateMenu> {
constructor(props: IPropsMenu) {
super(props);
this.state = {
menu: [
{
name: 'screen1.name',
fallbackName: 'Screen 1',
icon: 'dice-multiple-outline',
iconFocused: 'dice-multiple',
onPress: this.props.navigation.navigate.bind(this, 'screen1')
},
{
name: 'screen2.name',
fallbackName: 'Screen 2',
icon: 'drama-masks',
iconFocused: 'drama-masks',
onPress: this.props.navigation.navigate.bind(this, 'screen2')
}
]
}
}
renderItem = (item : IListItem) => {
const { i18n } = this.props.state.routes[0].params;
return (
<DrawerItem
label={ i18n.t(item.name, item.fallbackName) }
onPress={ item.onPress ? item.onPress: () => {} }
icon={ ({ focused, color, size }) => <List.Icon color={color} style={[styles.icon, {width: size, height: size }]} icon={(focused ? item.iconFocused : item.icon) || ''} /> }
/>
);
};
render() {
const { headerHeight } = this.props;
const { menu } = this.state;
const { Theme } = this.props.state.routes[0].params;
return (
<View>
<View style={{
backgroundColor: Theme.colors.primary,
height: headerHeight ?? 0,
}}>
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
}}>
<View style={{
flexDirection: 'row',
alignItems: 'center',
marginBottom: 5,
marginLeft: 5
}}>
<Title style={{ color: Theme.colors.text, marginLeft: 5 }}>
Title
</Title>
</View>
</View>
</View>
<FlatList
data={menu}
keyExtractor={item => item.name}
renderItem={({item}) => this.renderItem(item)}
/>
</View>
);
};
}
export default withHeightHook(Menu);
const styles = StyleSheet.create({
icon: {
alignSelf: 'center',
margin: 0,
padding: 0,
height:20
},
logo: {
width: 24,
height: 24,
marginHorizontal: 8,
alignSelf: 'center'
},
});
The solution to my issue was to encapsulate the drawer component in a native stack component. The 'Hamburger' icon works as expected, thanks for all the help and suggestions.
// Import Screens
import DrawRouter from './DrawRouter';
const Stack = createNativeStackNavigator<RootStackParamList>();
export default (): React.ReactElement => {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name="Main" component={DrawRouter} />
</Stack.Navigator>
</NavigationContainer>
);
};
Add the toogleDrawer() method to your onPress event on your Drawer.Navigator component:
onPress={()=> navigation.toggleDrawer()
Hello guys so I wanted to add a navigation DRAWER inside my main screen and I did not know how to nest it with the already existing stack navigator ,
this is my navigation component :
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import ProductsOverviewScreen from "../screens/shop/ProductsOverviewScreen";
import ProductDetails from "../screens/shop/ProductDetailScreen";
import { HeaderButtons,Item } from "react-navigation-header-buttons";
import HeaderButton from '../components/UI/HeaderButton'
import CartScreen from "../screens/shop/CartScreen";
import OrdersScreen from "../screens/shop/OrdersScreen";
const RootNavigation=()=> {
const Stack = createStackNavigator();
const NavigationDrawerStructure = (props)=> {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={()=> toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png'}}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
const screenOptions ={
headerShown:true,
headerStyle: {
backgroundColor: 'white',},
headerTintColor: 'aqua',
headerTitleStyle: {
fontWeight: 'bold',
},
};
return(
<NavigationContainer>
<Stack.Navigator initialRouteName='ProductsOverview' screenOptions={screenOptions}>
<Stack.Screen name='ProductsOverview' component={ProductsOverviewScreen} options={({navigation,route})=>({title:'All Products',headerTitleStyle:{fontFamily:'open-sans-bold'},
headerRight:()=>( <HeaderButtons HeaderButtonComponent={HeaderButton}><Item title ='Cart' iconName='md-cart' onPress={()=>{navigation.navigate('CartScreen')}}/></HeaderButtons>)})}/>
<Stack.Screen name='ProductsDetail' component={ProductDetails} options={({route})=>({title:route.params.productTitle,headerTitleStyle:{fontFamily:'open-sans-bold'}})} />
<Stack.Screen name='CartScreen' component={CartScreen} options={{title:'Cart Items', headerTitleStyle:{fontFamily:'open-sans-bold'}}} />
<Stack.Screen name='OrdersScreen' component={OrdersScreen} options={{title:'Orders '}}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default RootNavigation;
and this is my app.js
import { StatusBar } from 'expo-status-bar';
import { StyleSheet } from 'react-native';
import {createStore , combineReducers} from 'redux';
import { Provider} from 'react-redux';
import AppLoading from 'expo-app-loading';
import * as Font from 'expo-font';
import productsReducer from './store/reducers/products';
import {composeWithDevTools} from 'redux-devtools-extension'
import RootNavigation from './navigation/ShopNavigation';
import cartReducer from './store/reducers/cart'
import { useState } from 'react';
import ordersReducer from './store/reducers/orders'
const rootReducer=combineReducers({
products: productsReducer,
cart: cartReducer,
orders:ordersReducer,
});
const store = createStore(rootReducer,composeWithDevTools());
const fetchFonts=()=>{
return Font.loadAsync({
'open-sans': require('./assets/fonts/OpenSans-Regular.ttf'),
'open-sans-bold': require('./assets/fonts/OpenSans-Bold.ttf')
})
}
export default function App() {
const [fontLoaded,setfontLoaded]= useState(false);
if (!fontLoaded) {
return (
<AppLoading
startAsync={fetchFonts}
onFinish={()=>setfontLoaded(true)}
onError={console.warn}
/>
);
}
return (
<Provider store={store}>
<RootNavigation />
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
can you give me an idea how to nest them together I tried using the docs but still full of errors
and Thanks
Drawer Navigator must be a parent to both Stack and Tab navigators. With that knowledge, let we refactor our code as below:
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import ProductsOverviewScreen from "../screens/shop/ProductsOverviewScreen";
import ProductDetails from "../screens/shop/ProductDetailScreen";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/UI/HeaderButton";
import CartScreen from "../screens/shop/CartScreen";
import OrdersScreen from "../screens/shop/OrdersScreen";
import { createDrawerNavigator } from "#react-navigation/drawer";
const RootNavigation = () => {
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const AppStack = () => (
<Stack.Navigator
initialRouteName="ProductsOverview"
screenOptions={screenOptions}
>
<Stack.Screen
name="ProductsOverview"
component={ProductsOverviewScreen}
options={({ navigation, route }) => ({
title: "All Products",
headerTitleStyle: { fontFamily: "open-sans-bold" },
headerRight: () => (
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
title="Cart"
iconName="md-cart"
onPress={() => {
navigation.navigate("CartScreen");
}}
/>
</HeaderButtons>
),
})}
/>
<Stack.Screen
name="ProductsDetail"
component={ProductDetails}
options={({ route }) => ({
title: route.params.productTitle,
headerTitleStyle: { fontFamily: "open-sans-bold" },
})}
/>
<Stack.Screen
name="CartScreen"
component={CartScreen}
options={{
title: "Cart Items",
headerTitleStyle: { fontFamily: "open-sans-bold" },
}}
/>
<Stack.Screen
name="OrdersScreen"
component={OrdersScreen}
options={{ title: "Orders " }}
/>
</Stack.Navigator>
);
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="MainStack" component={AppStack} />
</Drawer.Navigator>
</NavigationContainer>
);
};
export default RootNavigation;
I omitted component code below as can't access drawer.
const NavigationDrawerStructure = (props)=> {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{ flexDirection: 'row' }}>
<TouchableOpacity onPress={()=> toggleDrawer()}>
{/*Donute Button Image */}
<Image
source={{uri: 'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png'}}
style={{ width: 25, height: 25, marginLeft: 5 }}
/>
</TouchableOpacity>
</View>
);
}
Here a minified version of working implementation
https://snack.expo.dev/#emmbyiringiro/69dc5b
I have a problem with react native navigation screen
Here is my problem picture:
enter image description here
As you can see the navigation screen is shown smaller than the simulator screen size.
Here is my related code
Navigation code:
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 Ionicons from 'react-native-vector-icons/Ionicons';
import {Text, Dimensions} from 'react-native';
import HomeScreen from '../screens/HomeScreen';
import AboutScreen from '../screens/AboutScreen';
import ProfileScreen from '../screens/ProfileScreen';
const fullScreenWidth = Dimensions.get('window').width;
const Stack = createStackNavigator();
function HomeStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
</Stack.Navigator>
);
}
function AboutStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="AboutScreen" component={AboutScreen} />
</Stack.Navigator>
);
}
function ProfileStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="ProfileScreen" component={ProfileScreen} />
</Stack.Navigator>
);
}
const Tab = createBottomTabNavigator();
function Navigation(props) {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({route}) => ({
headerTitle: () => {
return <Text>Header</Text>;
},
tabBarIcon: ({focused, color, size, padding}) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'About') {
iconName = focused
? 'information-circle'
: 'information-circle-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return (
<Ionicons
name={iconName}
size={size}
color={color}
style={{paddingBottom: padding}}
/>
);
},
tabBarActiveTintColor: 'lightseagreen',
tabBarInactiveTintColor: 'grey',
tabBarLableStyle: {fontSize: 16},
tabBarstyle: {width: fullScreenWidth},
})}>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="About" component={AboutStackScreen} />
<Tab.Screen name="Profile" component={ProfileStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
export default Navigation;
Screen code(each screen has same format):
import React from 'react';
import {SafeAreaView, Text, StyleSheet} from 'react-native';
const HomeScreen = props => {
return (
<SafeAreaView style={styles}>
<Text>Home Screen</Text>
</SafeAreaView>
);
};
export default HomeScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
App screen:
import 'react-native-gesture-handler';
import * as React from 'react';
import {useState, useEffect} from 'react';
import {Text, View, StyleSheet, Button, Linking} from 'react-native';
import Amplify, {Auth, Hub} from 'aws-amplify';
import awsconfig from './src/aws-exports';
import {Authenticator, withOAuth} from 'aws-amplify-react-native';
import InAppBrowser from 'react-native-inappbrowser-reborn';
import SignUp from './src/components/auth/SignUp';
import ConfirmSignUp from './src/components/auth/ConfirmSignUp';
import SignIn from './src/components/auth/SignIn';
import ForgotPassword from './src/components/auth/ForgotPassword';
import ChangePassword from './src/components/auth/ChangePassword';
import Navigation from './src/components/navigation/Navigation';
import UserContext from './src/components/userContext/UserContext';
async function urlOpener(url, redirectUrl) {
await InAppBrowser.isAvailable();
const {type, url: newUrl} = await InAppBrowser.openAuth(url, redirectUrl, {
showTitle: false,
enableUrlBarHiding: true,
enableDefaultShare: false,
ephemeralWebSession: false,
});
if (type === 'success') {
Linking.openURL(newUrl);
}
}
Amplify.configure({
...awsconfig,
Analytics: {
disabled: true,
},
oauth: {
...awsconfig.oauth,
urlOpener,
},
});
function Home(props) {
return (
<View>
<Navigation {...props} />
<Button title="Sign Out" onPress={() => Auth.signOut()} />
</View>
);
}
const AuthScreens = props => {
console.log(props.authState);
switch (props.authState) {
case 'signIn':
return <SignIn {...props} />;
case 'signUp':
return <SignUp {...props} />;
case 'forgotPassword':
return <ForgotPassword {...props} />;
case 'confirmSignUp':
return <ConfirmSignUp {...props} />;
case 'changePassword':
return <ChangePassword {...props} />;
case 'signedIn':
return <Home />;
case 'verifyContact':
return <Home />;
default:
return <></>;
}
};
const App = props => {
const [user, setUser] = useState({});
useEffect(() => {
Hub.listen('auth', ({payload: {event, data}}) => {
switch (event) {
case 'signIn':
case 'cognitoHostedUI':
getUser().then(userData => setUser(userData));
break;
case 'signOut':
setUser(null);
break;
case 'signIn_failure':
case 'cognitoHostedUI_failure':
console.log('Sign in failure', data);
break;
}
});
getUser().then(userData => setUser(userData));
}, []);
function getUser() {
return Auth.currentAuthenticatedUser()
.then(userData => userData)
.catch(() => console.log('Not signed in'));
}
const {googleSignIn, facebookSignIn} = props;
return (
<View style={styles.container}>
<Authenticator
usernameAttributes="email"
hideDefault={true}
authState="signIn">
<AuthScreens />
</Authenticator>
{!user && (
<View style={{marginBottom: 200}}>
<Text style={{textAlign: 'center'}}> - OR - </Text>
<Button title="Login with Google" onPress={googleSignIn} />
<Button title="Login with Facebook" onPress={facebookSignIn} />
</View>
)}
</View>
);
};
export default withOAuth(App);
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
How to fix this to fill up simulator screen?
I solve this problem by myself.
Actually the problem is in tabBarStyle!!!!
This is fixed code in Navigation.js:
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 Ionicons from 'react-native-vector-icons/Ionicons';
import {Text, Dimensions} from 'react-native';
import HomeScreen from '../screens/HomeScreen';
import AboutScreen from '../screens/AboutScreen';
import ProfileScreen from '../screens/ProfileScreen';
const fullScreenWidth = Dimensions.get('window').width;
const Stack = createStackNavigator();
function HomeStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} />
</Stack.Navigator>
);
}
function AboutStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="AboutScreen" component={AboutScreen} />
</Stack.Navigator>
);
}
function ProfileStackScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="ProfileScreen" component={ProfileScreen} />
</Stack.Navigator>
);
}
const Tab = createBottomTabNavigator();
function Navigation(props) {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({route}) => ({
headerTitle: () => {
return <Text>Header</Text>;
},
tabBarIcon: ({focused, color, size, padding}) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'About') {
iconName = focused
? 'information-circle'
: 'information-circle-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return (
<Ionicons
name={iconName}
size={size}
color={color}
style={{paddingBottom: padding}}
/>
);
},
tabBarActiveTintColor: 'lightseagreen',
tabBarInactiveTintColor: 'grey',
tabBarLableStyle: {fontSize: 16},
tabBarStyle: {width: fullScreenWidth},
})}>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="About" component={AboutStackScreen} />
<Tab.Screen name="Profile" component={ProfileStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
export default Navigation;
I want to go out of top tab navigation but it unable to navigate. It's giving error The action 'NAVIGATE' with payload {"name":"LoginPage"} was not handled by any navigator.
Do you have a screen named 'LoginPage'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator
I use nesting navigation also but not work. My Screens are below
Top tab navigation screen
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
import ProfileData from './profiledata';
import ProfileLikeData from './profilelikedata';
import Fontisto from 'react-native-vector-icons/Fontisto';
const Tab = createMaterialTopTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color }) => {
let iconName;
let size;
if (route.name === 'Data') {
iconName = focused
? 'nav-icon-grid'
: 'nav-icon-grid';
size = focused
? 25
: 25;
} else if (route.name === 'Like') {
iconName = focused ? 'heart' : 'heart';
size = focused
? 20
: 20;
}
return <Fontisto name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: '#d40786',
inactiveTintColor: 'white',
showIcon:true,
showLabel:false,
indicatorStyle: {
width: 0, height: 0, elevation: 0,
},
tabStyle: { width: wp('52%'),borderRightWidth:1,borderColor:'white' },
style: { backgroundColor:'trasparent',borderTopWidth:0.5,borderColor:'white',paddingBottom:5 },
}}
>
<Tab.Screen name="Data" component={ProfileData} />
<Tab.Screen name="Like" component={ProfileLikeData} />
</Tab.Navigator>
</NavigationContainer>
);
}
profiledata.js
import React from 'react';
import { View, StyleSheet, Text,ImageBackground,TouchableOpacity,Image } from 'react-native';
import { FlatGrid } from 'react-native-super-grid';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen';
import { RFPercentage, RFValue } from "react-native-responsive-fontsize";
import Toast from 'react-native-simple-toast';
export default class ProfileData extends React.Component {
constructor(props) {
super(props);
this.state = {
videos:[],
loginid:'',
paused:true,
};
}
static navigationOptions = {
headerShown: false,
};
render() {
const { navigate } = this.props.navigation;
return (
<View style={styles.container}>
<FlatGrid
data={this.state.videos}
spacing={0}
renderItem={({ item }) => (
<TouchableOpacity onPress={()=>navigate('LoginPage')} style={{flex:1}}>
// some data
</TouchableOpacity>
)}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
// paddingHorizontal:wp('2%'),
backgroundColor:'black',
height: hp('100%'),
},
});
You should create another stack that has your login screen or add the login screen in the tab navigator.
for the first do something like this in your app.js
import { createStackNavigator } from '#react-navigation/stack';
import LoginScreen from './LoginScreen'; //Just import the login screen
const AuthStack = createStackNavigator();
const AuthStackScreen = () => (
<AuthStack.Navigator>
<AuthStack.Screen
name="LoginPage"
component={LoginScreen}
/>
</AuthStack.Navigator>
);
//Then in your profiledata.js;
<TouchableOpacity onPress={()=>navigate('LoginPage')} style={{flex:1}}>
// some data
</TouchableOpacity>
And for the second option just add the login screen in your tab navigator;
<Tab.Screen name="Data" component={ProfileData} />
<Tab.Screen name="Like" component={ProfileLikeData} />
<Tab.Screen name="LoginPage" component={LoginScreen} /> //Don't forget to import it