React Native BottomTabNavigator Icon remove - react-native-tabnavigator

explanatory photo
I want to remove the 'X' mark in the picture and move it to the alarm part at the top. Is it possible?
Can I move the bottom navigation button to the header?
<Tab.Navigator
screenOptions={{
headerRight: () => (
<NotiIconBtn onPress={() => navigate("Tabs", { screen: "Alarm" })}>
<NotiIcon source={require("../public/img/notiIcon.png")} />
</NotiIconBtn>
),
>
<Tab.Screen
name="MyPage"
component={MyPage}
options={{
headerShown: true,
headerBackTitleVisible: true,
title: "마이페이지",
tabBarIcon: ({ focused, color, size }) => {
return !focused ? (
<>
<Img source={require("../public/img/mypageIcon.png")} />
<Text>마이페이지</Text>
</>
) : (
<>
<Img source={require("../public/img/mypageAIcon.png")} />
<ActiveText>마이페이지</ActiveText>
</>
);
},
}}
/>
skip
.
.
.
<Tab.Screen name="Alarm" component={Alarm} />
</Tab.Navigator>

Related

How can I make space between the navigation elements in Material Top Tab Navigation?

I have the below code:
const TopNavBar = () => {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={{}}
style={{paddingTop: StatusBar.currentHeight}}>
<Tab.Screen
options={{
title: ({color, focused}) => (
<Icon
size={25}
name={focused ? 'home' : 'home-outline'}
color={focused ? 'blue' : '#272727'}
/>
),
}}
component={Profile}
name="Home"
/>
<Tab.Screen
options={{
title: ({color, focused}) => (
<Icon
size={25}
name={focused ? 'person' : 'person-outline'}
color={focused ? 'blue' : '#272727'}
/>
),
}}
component={Profile}
name="Profile"
/>
</Tab.Navigator>
</NavigationContainer>
);
};
Which outputs:
But what I want is this:
Essentially only the profile button and the drawer only clickable
How can I achieve this?

React Native Firebase App: Change Stack.Screen onAuthStateChange

I have a React-Native (sdk 46.0) Firebase app. I want to make it so that when the user is signed in, he moves from the LoginScreen to to the HomeScreen. Code is shown below.
// screens/LoginScreen.js >>
...
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const navigation = useNavigation();
const handleLogin = () => {
auth
.signInWithEmailAndPassword(email, password)
.then((userCredentials) => {
const user = userCredentials.user;
console.log("Logged in with:", user.email);
})
.catch((error) => alert(error.message));
};
...
<View style={styles.inputContainer}>
<Input
style={styles.input}
blurOnSubmit
autoCorrect={false}
placeholder="jdoe#ernestkoliqi.com"
placeholderTextColor="#666"
value={email}
onChangeText={(text) => setEmail(text)}
selectTextOnFocus
keyboardType="email-address"
/>
<Input
style={styles.input}
blurOnSubmit
autoCorrect={false}
placeholder="Password"
placeholderTextColor="#666"
bool={true}
value={password}
onChangeText={(text) => setPassword(text)}
selectTextOnFocus
/>
</View>
<View style={styles.buttonContainerModal}>
<TouchableOpacity onPress={handleLogin}>
<View style={styles.ctaBtnModal}>
<Text style={styles.loginBtn}>Log In</Text>
</View>
</TouchableOpacity>
...
// App.js
...
function Home() {
return <HomeScreen />;
}
function News() {
return <NewsScreen />;
}
function Calendar() {
return <CalendarScreen />;
}
function Login() {
return <LoginScreen />;
}
function Feed() {
return (
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === "Home") {
iconName = focused ? "home" : "home-outline";
} else if (route.name === "News") {
iconName = focused ? "newspaper" : "newspaper-outline";
} else if (route.name === "Calendar") {
iconName = focused ? "calendar" : "calendar-outline";
}
return <Ionicons name={iconName} size={size} color={color} />;
},
activeTintColor: Colors.primary,
inactiveTintColor: "gray",
showLabel: true,
showIcon: true,
style: {
paddingBottom: 4.25,
paddingTop: 4.25,
},
})}
>
<Tab.Screen
name="Home"
component={Home}
options={{ headerShown: false }}
/>
<Tab.Screen
name="Calendar"
component={Calendar}
options={{ headerShown: false }}
/>
<Tab.Screen
name="News"
component={News}
options={{ headerShown: false }}
/>
</Tab.Navigator>
);
}
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
export default function App() {
return (
<SafeAreaView style={styles.screen}>
<StatusBar barStyle="light-content" translucent={true} />
<NavigationContainer theme={appTheme}>
<Stack.Navigator>
<Stack.Screen component={Login} options={{ headerShown: false }} name="Login" />
<Stack.Screen component={Feed} name="Feed" />
</Stack.Navigator>
<LoginScreen />
</NavigationContainer>
</SafeAreaView>
);
}
...
The code above shows the file structure and the code contained in the files relative to the topic. How can I manage to change Stack.Screen when user==True?
You need a state that can be changed in the Login component. You could use a Context for this purpose.
export const AppContext = React.createContext({});
export default function App() {
const [isSignedIn, setIsSignedIn] = React.useState(false);
const contextValue = React.useMemo(() => ({
isSignedIn,
setIsSignedIn
}), [isSignedIn])
return (
<SafeAreaView style={styles.screen}>
<StatusBar barStyle="light-content" translucent={true} />
<AppContext.Provider value={contextValue}>
<NavigationContainer theme={appTheme}>
<Stack.Navigator>
{
!isSignedIn ? (
<Stack.Screen component={Login} options={{ headerShown: false }} name="Login" />
) : (
<Stack.Screen component={Feed} name="Feed" />
)
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>
</SafeAreaView>
);
}
The Login screen can access the context and change it if the user logs in successfully.
const Login = (props) => {
const { setIsSignedIn } = useContext(AppContext);
const handleLogin = () => {
auth
.signInWithEmailAndPassword(email, password)
.then((userCredentials) => {
const user = userCredentials.user;
console.log("Logged in with:", user.email);
// success ?
setIsSignedIn(true);
})
.catch((error) => alert(error.message));
};
...
}

How do I render different Screens of an iOS app with React Native and Firebase/Firestore based on a user's role (provider or customer) after login?

I'm creating an app with React Native and Firebase/Firestore, and I need the app to show different screens based on the role of the user's account (Provider or Customer). After a user logs into their account, the app should check their role data from Firebase and render a different screen based on it. So the app will first evaluate the condition to see if they're logged in. Then it will evaluate the condition to see if they're a Provider or Customer and then render the proper screen (either the Login, ProviderHomeScreen, or CustomerHomeScreen).
I've tried to use the condition:
const user = firebase.auth().currentUser;
var role;
if (user != null) {
role = user.role;
console.log(role);
}
if (isLoggedIn) {
if (user.role === 'provider') {
return (
<NavigationContainer>
<ProviderStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Provider Home'}
component={ProviderHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</ProviderStack.Navigator>
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<CustomerStack.Navigator>
<Stack.Screen
name={'Customer Home'}
component={CustomerHomeTabNavigator}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name={'Search'}
component={SearchScreen}
options={{
title: 'Search Availa Providers',
}}
/>
</CustomerStack.Navigator>
</NavigationContainer>
);
}
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen
name="Customer Sign-up"
component={CustomerRegistrationScreen}
/>
<Stack.Screen
name="Provider Sign-up"
component={ProviderRegistrationScreen}
/>
</Stack.Navigator>
</NavigationContainer>
but when I console.log the user.role, it says undefined in the console, and the app just renders the CustomerHomeScreen with the CustomerHomeTabNavigator.
Please help me successfully access the role data of the currently signed-in user from Firestore and create conditions to render the proper screens for the proper role of the users.
Right now, this is what my code looks like for App.js:
import 'react-native-gesture-handler';
import React, {useEffect, useState} from 'react';
import {View, Text} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createNativeStackNavigator} from '#react-navigation/native-stack';
import {createStackNavigator} from '#react-navigation/stack';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import CustomerHomeScreen from '../Availa/src/Customer/screens/Home/index';
import Fontisto from 'react-native-vector-icons/Fontisto';
import FontAwesome from 'react-native-vector-icons/FontAwesome';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
import Feather from 'react-native-vector-icons/Feather';
import AntDesign from 'react-native-vector-icons/AntDesign';
import Ionicons from 'react-native-vector-icons/Ionicons';
import {firebase} from '../Availa/src/firebase/config';
import 'firebase/auth';
import firestore from '#react-native-firebase/firestore';
import 'firebase/firestore';
import 'react-native-gesture-handler';
Fontisto.loadFont();
FontAwesome.loadFont();
Feather.loadFont();
AntDesign.loadFont();
Ionicons.loadFont();
import SearchScreen from '../Availa/src/Customer/screens/SearchScreen/index';
import ProfileScreen from '../Availa/src/Customer/screens/ProfileScreen/index';
import {
LoginScreen,
CustomerRegistrationScreen,
ProviderRegistrationScreen,
} from './src/screens';
import 'firebase/auth';
import {decode, encode} from 'base-64';
if (!global.btoa) {
global.btoa = encode;
}
if (!global.atob) {
global.atob = decode;
}
const ProviderStack = createNativeStackNavigator();
const ProviderStackScreen = () => {
return (
<ProviderStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Home'}
component={ProviderHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</ProviderStack.Navigator>
);
};
const ProviderTab = createBottomTabNavigator();
const ProviderHomeTabNavigator = () => {
return (
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#007FFF',
}}>
<Tab.Screen
name={'Provider'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Fontisto name="home" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'My List'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<FontAwesome name="heart-o" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Appointments'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="calendar" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Messages'}
component={ProviderHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Feather name="message-square" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Profile'}
component={ProfileScreen}
options={{
tabBarIcon: ({color}) => (
<Ionicons name="person-circle-outline" size={25} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
const CustomerStack = createNativeStackNavigator();
const CustomerStackScreen = () => {
return (
<CustomerStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Home'}
component={CustomerHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</CustomerStack.Navigator>
);
};
const Tab = createBottomTabNavigator();
const CustomerHomeTabNavigator = () => {
return (
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#1cd478',
}}>
<Tab.Screen
name={'Home'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Fontisto name="home" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'My List'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<FontAwesome name="heart-o" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Appointments'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<AntDesign name="calendar" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Messages'}
component={CustomerHomeScreen}
options={{
tabBarIcon: ({color}) => (
<Feather name="message-square" size={25} color={color} />
),
}}
/>
<Tab.Screen
name={'Profile'}
component={ProfileScreen}
options={{
tabBarIcon: ({color}) => (
<Ionicons name="person-circle-outline" size={25} color={color} />
),
}}
/>
</Tab.Navigator>
);
};
const chooseScreen = user => {
if (user?.role === 'provider') {
ProviderStackScreen();
}
CustomerStackScreen();
};
const Stack = createStackNavigator();
export default function App() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loading, setLoading] = useState(true);
const firestore = firebase.firestore;
const auth = firebase.auth;
const user = firebase.auth().currentUser;
// //to check if Firebase has been initialized
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
} else {
firebase.app();
}
firebase.auth().onAuthStateChanged(user => {
if (user != null) {
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
});
var role;
if (user != null) {
role = user.role;
console.log(role);
}
if (isLoggedIn) {
if (user.role === 'provider') {
return (
<NavigationContainer>
<ProviderStack.Navigator>
<Stack.Navigator>
<Stack.Screen
name={'Provider Home'}
component={ProviderHomeTabNavigator}
options={{
headerShown: false,
}}
/>
</Stack.Navigator>
</ProviderStack.Navigator>
</NavigationContainer>
);
} else {
return (
<NavigationContainer>
<CustomerStack.Navigator>
<Stack.Screen
name={'Customer Home'}
component={CustomerHomeTabNavigator}
options={{
headerShown: false,
}}
/>
<Stack.Screen
name={'Search'}
component={SearchScreen}
options={{
title: 'Search Availa Providers',
}}
/>
</CustomerStack.Navigator>
</NavigationContainer>
);
}
}
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen
name="Customer Sign-up"
component={CustomerRegistrationScreen}
/>
<Stack.Screen
name="Provider Sign-up"
component={ProviderRegistrationScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
Also, this is what my LoginScreen.js looks like:
import React, {useState} from 'react';
import {Image, Text, TextInput, TouchableOpacity, View} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import styles from './styles';
import {firebase} from '../../firebase/config';
export default function LoginScreen({navigation}) {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const onLoginPress = () => {
firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(response => {
const uid = response.user.uid;
const usersRef = firebase.firestore().collection('users');
usersRef
.doc(uid)
.get()
.then(firestoreDocument => {
if (!firestoreDocument.exists) {
alert('User does not exist');
return;
}
const user = firestoreDocument.data();
if (user.role === 'provider') {
navigation.navigate('Provider Home', {user});
} else {
navigation.navigate('Customer Home', {user});
}
})
.catch(error => {
alert(error);
});
})
.catch(error => {
alert(error);
});
};
return (
<View style={styles.container}>
<KeyboardAwareScrollView
style={{flex: 1, width: '100%'}}
keyboardShouldPersistTaps="always">
<Image
style={styles.logo}
source={require('../../../assets/availalogo.png')}
/>
<TextInput
style={styles.input}
placeholder="Email"
placeholderTextColor="#aaaaaa"
onChangeText={text => setEmail(text)}
value={email}
underlineColorAndroid="transparent"
autoCapitalize="none"
/>
<TextInput
style={styles.input}
placeholderTextColor="#aaaaaa"
secureTextEntry
placeholder="Password"
onChangeText={text => setPassword(text)}
value={password}
underlineColorAndroid="transparent"
autoCapitalize="none"
/>
<TouchableOpacity style={styles.button} onPress={() => onLoginPress()}>
<Text style={styles.buttonTitle}>Log in</Text>
</TouchableOpacity>
<Text style={styles.footerText}>Don't have an account?</Text>
<TouchableOpacity
style={{
backgroundColor: '#ED2939', //#118C4F?
marginLeft: 30,
marginRight: 30,
marginTop: 20,
height: 48,
borderRadius: 5,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => navigation.navigate('Provider Sign-up')}>
<Text style={{color: 'white', fontSize: 16, fontWeight: 'bold'}}>
Sign Up as Availa Provider
</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: '#007FFF',
marginLeft: 30,
marginRight: 30,
marginTop: 20,
height: 48,
borderRadius: 5,
alignItems: 'center',
justifyContent: 'center',
}}
onPress={() => navigation.navigate('Customer Sign-up')}>
<Text style={{color: 'white', fontSize: 16, fontWeight: 'bold'}}>
Sign Up as Customer
</Text>
</TouchableOpacity>
</KeyboardAwareScrollView>
</View>
);
}
Are you adding the role in custom claims?
if so you need to get the the claims from getIdTokenResult
firebase.auth().currentUser.getIdTokenResult()
.then((idTokenResult) => {
const role = idTokenResult.claims.role;
})
.catch((error) => {
console.log(error);
});
Also I personally keep the firebase initialization outside of the component and
firebase.auth().onAuthStateChanged(user => {
if (user != null) {
setIsLoggedIn(true);
} else {
setIsLoggedIn(false);
}
});
inside useEffect, so instead of setIsLoggedIn would do setUser and in your case after you get the role you can set it in a different state.

SafeAreaView implementation on iPhone 11

I'm trying to add a SafeAreaView so my icons don't get squished together like shown in the image.
But it seems the SafeAreaView just pushes the contents up instead.
This is how I've currently Implemented it/
const BottomTabs = () => (
<SafeAreaView style={styles.container}>
<DevSupport />
<Tab.Navigator>
<Tab.Screen
name="Home"
component={FeaturedScreen}
options={{
unmountOnBlur: true,
tabBarLabel: 'Home',
tabBarIcon: ({ color }) => (
<Icons.IconHome width={ICON_SIZE} height={ICON_SIZE} color={color} />
),
}}
/>
</Tab.Navigator>
</SafeAreaView>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
Any tips on where I'm going wrong? Or am I simply adding the SafeAreaView on the wrong screen?
Without SafeArea it looks like the following:
BottomTab had SafeAreaView so you don't need to wrap it in SafeAreaView.
const BottomTabs = () => (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={FeaturedScreen}
options={{
unmountOnBlur: true,
tabBarLabel: 'Home',
tabBarIcon: ({ color }) => (
<Icons.IconHome width={ICON_SIZE} height={ICON_SIZE} color={color} />
),
}}
/>
</Tab.Navigator>
);
const styles = StyleSheet.create({
container: {
flex: 1,
},
});

React-Native. TouchableOpacity works only when tap with 2 fingers

I'm running my app via React-Native and native-base and I got some problems with component TouchableOpacity.
When I'm writing my component like
<TouchableOpacity onPress={() => {this.onPress()}}>
<Text>Some text</Text>
</TouchableOpacity
It works perfect, when I tap with 1 finger
But when I'm running like this - My Code:
renderList () {
return (
<List>
{this.state.data.map( ( restaurant, index ) => {
return (
<TouchableOpacity onPress={() => {
this.onPress();
}} key={index}>
<View style={styles.example}>
<ListItem>
<Thumbnail square size={80} source={{ uri: 'Image URL' }}/>
<Body>
<Text>{restaurant.title}</Text>
<Text note>{restaurant.shortDescription}</Text>
</Body>
</ListItem>
</View>
</TouchableOpacity>
);
} )}
</List>
);
}
It is ignoring 1 tap, twice tap etc, it is only working when I tap with 2 fingers. Didn't find any info about this problem. May be some one know how to solve this?
Thanks
Added FullCode:
import React, { Component } from 'react';
import {
Container,
Button,
Header,
Left,
Icon,
Body,
Right,
Text,
Content,
List,
ListItem,
Thumbnail
} from 'native-base';
import { StyleSheet, TouchableOpacity, View } from 'react-native';
export default class Restaurants extends Component {
constructor ( props ) {
super( props );
this.state = {
data: this.props.data
};
}
onPress () {
console.log( 'Hello' );
}
renderList () {
return (
<List>
{this.state.data.map( ( restaurant, index ) => {
return (
<TouchableOpacity onPress={() => {
this.onPress();
}} key={index}>
<View style={styles.example}>
<ListItem>
<Thumbnail square size={80} source={{ uri: 'Image URL' }}/>
<Body>
<Text>{restaurant.title}</Text>
<Text note>{restaurant.shortDescription}</Text>
</Body>
</ListItem>
</View>
</TouchableOpacity>
);
} )}
</List>
);
}
render () {
return (
<Container>
<Header style={styles.header}>
<Left>
<Button transparent>
<Icon style={styles.header_icon} name="arrow-back"/>
</Button>
</Left>
<Body>
<Text>Ресторанны</Text>
</Body>
<Right>
<Button transparent>
<Icon style={styles.header_icon} name="restaurant"/>
</Button>
</Right>
</Header>
<Content>
{this.renderList()}
</Content>
</Container>
);
}
}
const styles = StyleSheet.create( {
header: {
backgroundColor: '#606dff'
},
header_icon: {
color: 'black'
},
example: {
backgroundColor: 'red'
}
} );
As we spoken, I'll post it here so it's better to read and copy the code.
Try this:
renderList() {
return (
<List>
{
this.state.data.map( ( restaurant, index ) => {
return (
<ListItem>
<TouchableOpacity
onPress={() => {
this.onPress();
}}
key={index}
>
<View style={styles.example}>
<Thumbnail square size={80} source={{ uri: 'Image URL' }}/>
<Body>
<Text>{restaurant.title}</Text>
<Text note>{restaurant.shortDescription}</Text>
</Body>
</View>
</TouchableOpacity>
</ListItem>
);
});
}
</List>
);
}
I swapped <ListItem> and <TouchableOpacity>
There might be any conflict the way you wrote.
Let me know if it worked.

Resources