How to add Fonts into React Expo Project - reactjs

I am having issues using downloaded fonts into my Expo project.
I have added all the fonts I wanted into assets/fonts folder but even if there are a lot of examples (documentation: https://docs.expo.io/versions/latest/sdk/font/#usefonts) on how to do it I still not have found the solution.
At this moment I am using two Main scripts (App.js and AppScreen.js)
I am looking to add fonts on all the project.
App.js Script:
import React from 'react'
import {Provider} from 'react-redux'
import {createStore, combineReducers} from 'redux'
import { StyleSheet, Text, View, Button, ActivityIndicator } from 'react-native'
import { NavigationContainer } from '#react-navigation/native'
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs'
import { createStackNavigator } from '#react-navigation/stack'
import { FontAwesome5 } from '#expo/vector-icons'
// Screens
import HomeScreen from './components/screens/HomeScreen'
import ExchangeScreen from './components/screens/ExchangeScreen'
import MessageScreen from './components/screens/MessageScreen'
import NewAdScreen from './components/screens/NewAdScreen'
import ProfileScreen from './components/screens/ProfileScreen'
import AppScreen from './components/screens/AppScreen'
// Reducers
import userConnected from './components/reducers/userConnected'
import { Extrapolate } from 'react-native-reanimated'
import { useFonts } from 'expo-font';
const store = createStore(combineReducers({ userConnected }));
function App() {
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
// const StackMenu = () => {
// return (
// <NavigationContainer>
// <Stack.Navigator>
// <Stack.Screen name='App' component={AppScreen}/>
// </Stack.Navigator>
// </NavigationContainer>
// )
// }
let TabMenu = () => {
return (
<Tab.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = 'home'
} else if (route.name === 'Exchange') {
iconName = 'exchange-alt'
} else if (route.name === 'Message') {
iconName = 'comment-dots'
} else if (route.name === 'NewAd') {
iconName = 'plus-square';
} else if (route.name === 'Profile') {
iconName = 'user';
}
// You can return any component that you like here!
// return <Ionicons name={iconName} size={size} color={color} />;
return <FontAwesome5 name={iconName} size={size} color={color} />
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Exchange" component={ExchangeScreen} />
<Tab.Screen name="Message" component={MessageScreen} />
<Tab.Screen name="NewAd" component={NewAdScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
)
}
return (
<Provider store={store}>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
<Stack.Screen name='App' component={AppScreen} />
<Stack.Screen name='TabMenu' component={TabMenu} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
export default App;
And this AppScreen.js :
// This component implements the "Accueil" screen
import { StatusBar } from "expo-status-bar";
import React, { Component, useEffect, useState } from 'react'
import { StyleSheet, Text, View, Image, ScrollView } from 'react-native'
import { connect } from 'react-redux'
import AsyncStorage from '#react-native-async-storage/async-storage'
import { Input, Button, Overlay, CheckBox } from 'react-native-elements'
import { black, cranberrie, darkGreen, green, grey } from '../../tools/globalVariables'
import { storeLocalData } from '../../tools/functions'
import { useFonts } from 'expo-font';
import * as Font from 'expo-font';
const myIP = '##########'
function AppScreen(props) {
const [screen, setScreen] = useState(false)
const [modalSignUpVisible, setModalSignUpVisible] = useState(false)
const [modalSignInVisible, setModalSignInVisible] = useState(false)
const [firstName, setFirstName] = useState('')
const [lastName, setLastName] = useState('')
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
// States for Sign In
const [wrongPassSignIn, setWrongPassSignIn] = useState(false)
const [wrongEmailSignIn, setWrongEmailSignIn] = useState(false)
const [labelPassSignIn, setLabelPassSignIn] = useState('Mot de passe')
const [labelMailSignIn, setLabelMailSignIn] = useState('Email')
// States for Sign Up
const [wrongFirstName, setWrongFirstName] = useState(false)
const [wrongLastName, setWrongLastName] = useState(false)
const [wrongEmail, setWrongEmail] = useState(false)
const [wrongPassword, setWrongPassword] = useState(false)
const [labelFirstName, setLabelFirstName] = useState('Prénom')
const [labelLastName, setLabelLastName] = useState('Nom')
const [labelEmail, setLabelEmail] = useState('Email')
const [labelPassword, setLabelPassword] = useState('Mot de passe')
const [proAccount, setProAccount] = useState(false)
useEffect(() => {
// Show logo at first for 2 seconde, then the application screen
const timer = setTimeout(() => {
setScreen(true)
}, 2000);
const getData = async () => {
try {
const value = await AsyncStorage.getItem('userToken')
if (value !== null) {
const rawAnswer = await fetch(`http://${myIP}:3000/user/userInfos?token=${value}`)
const answer = await rawAnswer.json()
props.saveUser(answer.user)
props.navigation.navigate('TabMenu', { screen: 'Home' })
}
} catch (e) {
console.log('ERROR : ', e)
}
}
getData()
return () => clearTimeout(timer);
}, []);
/////// SIGN UP
const handleSignUp = async () => {
const dataUser = {
firstname: firstName,
lastname: lastName,
email,
password,
proAccount
}
///// Sending request to server //////
const rawAnswer = await fetch('http://' + myIP + ':3000/user/sign-up', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(dataUser)
});
const answer = await rawAnswer.json();
if (answer.result) {
// TO DO : STORE IN LOCAL STORAGE //
// Reset states values
setFirstName('')
setLastName('')
setEmail('')
setPassword('')
setProAccount(false)
setModalSignUpVisible(false)
props.navigation.navigate('TabMenu', { screen: 'Home' })
} else {
// Errors gestion
answer.error.map((err) => {
if (err.includes("firstname")) {
setWrongFirstName(true)
setLabelFirstName('Le prénom doit avoir 2 caractères minimum')
}
if (err.includes("lastname")) {
setWrongLastName(true)
setLabelLastName('Le nom doit avoir 2 caractères minimum')
}
if (err.includes("password")) {
setWrongPassword(true)
setLabelPassword('Le mot de passe doit faire entre 6 et 50 caractères')
}
if (err.includes("email")) {
setWrongEmail(true)
if (err.includes("existant")) {
setLabelEmail('Email déjà existant')
} else {
setLabelEmail("L'email doit être au bon format")
}
}
})
}
}
/////// SIGN IN
const handleSignIn = async () => {
console.log('Sign in')
const connexionData = {
email,
password
}
///// Sending request to server //////
const rawAnswer = await fetch('http://' + myIP + ':3000/user/sign-in', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(connexionData)
});
const answer = await rawAnswer.json();
console.log(answer.error)
if (answer.result) {
setEmail('')
setPassword('')
// Save in Local Storage
props.saveUser(answer.userFound)
await AsyncStorage.setItem('userToken', answer.userFound.token)
setModalSignInVisible(false)
props.navigation.navigate('TabMenu', { screen: 'Home' })
} else {
if (answer.error.indexOf('inexisting email') >= 0) {
setEmail('')
setPassword('')
setWrongEmailSignIn(true)
setLabelMailSignIn('Email inconnu')
setWrongPassSignIn(false)
setLabelPassSignIn('Mot de passe')
} else {
setPassword('')
setWrongPassSignIn(true)
setLabelPassSignIn('Mot de passe incorrect')
setWrongEmailSignIn(false)
setLabelMailSignIn('Email')
}
}
}
const handleCancel = () => {
// Reset state values and labels
setFirstName('')
setLastName('')
setEmail('')
setPassword('')
setProAccount(false)
setModalSignUpVisible(false)
setModalSignInVisible(false)
setWrongEmailSignIn(false)
setWrongPassSignIn(false)
setWrongPassword(false)
setWrongEmail(false)
setWrongFirstName(false)
setWrongLastName(false)
setLabelPassSignIn('Mot de passe')
setLabelMailSignIn('Email')
setLabelEmail('Email')
setLabelPassword('Mot de passe')
setLabelFirstName('Prénom')
setLabelLastName('Nom')
}
return (
<View>
{
screen ?
<View style={{ flexDirection: 'column', alignItems: 'center', backgroundColor: 'white', height: '100%', width: '100%' }}>
<Image source={require('../../assets/logoSmallBlack.png')} style={{ width: '30%', height: '25%', resizeMode: 'contain' }} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between', height: '50%', width: '100%' }}>
<Image source={require('../../assets/planteGauche.png')} style={{ width: '32%', height: '72%', resizeMode: 'contain' }} />
<Image source={require('../../assets/planteCentre.png')} style={{ width: '32%', height: '72%', resizeMode: 'contain', marginTop: 45 }} />
<Image source={require('../../assets/planteDroite.png')} style={{ width: '30%', height: '72%', resizeMode: 'contain' }} />
</View>
<StatusBar style="auto" />
<View >
<Text style={{ color: black, fontSize: 20, paddingBottom:-20 }}>Les plus belles plantes</Text>
<Text style={{ color: black, fontSize: 20, fontFamily: 'Recoleta'}}>près de chez toi !</Text>
</View>
{/* SIGN UP OVERLAY */}
<Overlay isVisible={modalSignUpVisible} onBackdropPress={() => { setModalSignUpVisible(!modalSignUpVisible); }}>
<View style={{ width: '80%' }}>
<ScrollView>
<Text style={{ textAlign: "center" }}>S'inscrire</Text>
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelFirstName} labelStyle={[wrongFirstName ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} placeholder='Entrez votre prénom' value={firstName} onChangeText={(value) => setFirstName(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelLastName} labelStyle={[wrongLastName ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} placeholder='Entrez votre nom' value={lastName} onChangeText={(value) => setLastName(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelEmail} labelStyle={[wrongEmail ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} placeholder='Entrez votre email' value={email} onChangeText={(value) => setEmail(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelPassword} labelStyle={[wrongPassword ? { color: cranberrie, fontSize: 13 } : { color: black, fontSize: 15 }]} secureTextEntry={true} placeholder='Entrez votre mot de passe' value={password} onChangeText={(value) => setPassword(value)} />
<CheckBox title='Je suis un professionnel' textStyle={{ fontSize: 12 }} containerStyle={{ backgroundColor: "transparent", borderWidth: 0, marginTop: -20, marginLeft: 0 }} checked={proAccount} onPress={() => { setProAccount(!proAccount) }} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between', width: '100%' }}>
<Button title='Annuler' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleCancel() }} />
<Button title='Valider mon inscription' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleSignUp() }} />
</View>
</ScrollView>
</View>
</Overlay>
{/* SIGN IN OVERLAY */}
<Overlay isVisible={modalSignInVisible} onBackdropPress={() => { setModalSignInVisible(!modalSignInVisible); }}>
<View style={{ width: '80%' }}>
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelMailSignIn} labelStyle={[{ fontSize: 15 }, wrongEmailSignIn ? { color: cranberrie } : { color: black }]} placeholder='Entrez votre email' value={email} onChangeText={(value) => setEmail(value)} />
<Input style={{ fontSize: 13 }} inputContainerStyle={{ width: '90%', borderBottomWidth: 0 }} label={labelPassSignIn} labelStyle={[{ fontSize: 15 }, wrongPassSignIn ? { color: cranberrie } : { color: black }]} secureTextEntry={true} placeholder='Entrez votre mot de passe' value={password} onChangeText={(value) => setPassword(value)} />
<View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
<Button title='Annuler' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleCancel() }} />
<Button title='Me connecter' buttonStyle={{ backgroundColor: black }} titleStyle={{ fontSize: 13 }} onPress={() => { handleSignIn() }} />
</View>
</View>
</Overlay>
<Button title="S'inscrire sur Plan.T" buttonStyle={{ backgroundColor: black, borderRadius: 5, width: '100%' }} onPress={() => { setModalSignUpVisible(true) }} />
<Button title="J'ai déjà un compte" buttonStyle={{ backgroundColor: 'white', borderRadius: 5, width: '100%', borderColor: '1px solid black' }} titleStyle={{ color: black }} onPress={() => { setModalSignInVisible(true) }} />
</View>
:
<View style={{ backgroundColor: darkGreen, height: '100%', justifyContent: 'center', alignItems: 'center' }}>
<Image source={require('../../assets/logo.png')} style={{ width: '70%', resizeMode: 'contain' }} />
</View>
}
</View>
)}
function mapDispatchToProps(dispatch) {
return {
saveUser: function (user) {
dispatch({ type: 'saveUser', user })
}
}
}
export default connect(
null,
mapDispatchToProps
)(AppScreen)
In my case I've added 26 fonts (see picture) :
Here the fonts I've added into asset/fonts folder
Let's say that I would like to use Recoleta Bold.otf inside a text part in AppScreen.js
How would you do this?
Thanks in advance for your time and help ! Much appreciate it.

I am adding a code snippet as an example from the official expo docs for easy reference.
import React from 'react';
import { Text, View } from 'react-native';
import AppLoading from 'expo-app-loading';
import { useFonts } from 'expo-font';
export default props => {
let [fontsLoaded] = useFonts({
'Inter-Black': require('./assets/fonts/Inter-Black.otf'),
});
if (!fontsLoaded) {
return <AppLoading />;
} else {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontFamily: 'Inter-Black', fontSize: 40 }}>Inter Black</Text>
<Text style={{ fontSize: 40 }}>Platform Default</Text>
</View>
);
}
};
Incase you want to dive more deep here is the link to official expo docs

Related

Data exists, but the map function returns no value React Native

I guess I'm not realizing something. I have the structure where I list the friends of the logged in user. Data appears to exist on console.log, but the map function does not work. Also, when I press the component in tab transitions, useEffect only works once. It doesn't work after that. Can you help me? Thanks.
App.js code
import { StatusBar } from 'expo-status-bar';
import React, { useState, useMemo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import SignIn from './SignIn';
import SignUp from './SignUp';
import Conversation from './Conversation';
import Contacts from './Contacts';
import Settings from './Settings';
import Chats from './Chats';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {Ionicons} from '#expo/vector-icons'
import { UserProvider } from './UserContext';
import { LogBox } from "react-native"
const Stack = createNativeStackNavigator();
const Tabs = createBottomTabNavigator();
const TabsNavigator = () => (
<Tabs.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
return <Ionicons name={route.name === "Chats" ? "chatbubble-ellipses-outline" : route.name === "Contacts" ? "people-outline" : "settings-outline"} color={color} size={size} />
}})}>
<Tabs.Screen name="Chats" component={Chats} />
<Tabs.Screen name="Contacts" component={Contacts} />
<Tabs.Screen name="Settings" component={Settings} />
</Tabs.Navigator>
);
export default function App() {
LogBox.ignoreAllLogs(true);
// const [lastUser, setLastUser] = useState('none');
// const value = useMemo(
// () => ({ lastUser, setLastUser }),
// [lastUser]
// );
return (
<UserProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen options={{headerShown : false }} name="SignIn" component={SignIn} />
<Stack.Screen
name="SignUp"
component={SignUp}
options={{ headerTitle:'Login', headerBackVisible : true, headerBackTitleVisible :true}}
/>
<Stack.Screen name="Home" component={TabsNavigator} options={{headerShown : false, headerBackTitleVisible : false}}/>
<Stack.Screen name="Contacts" component={Contacts} options={{ headerTitle:'ChatApp'}}/>
<Stack.Screen name="Conversation" component={Conversation} options={{ headerTitle:'ChatApp'}}/>
</Stack.Navigator>
</NavigationContainer>
</UserProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
SignIn.js code
import { useNavigation } from '#react-navigation/core'
import React, { useEffect, useState, createContext, useContext } from 'react'
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View, Image } from 'react-native'
import { borderColor } from 'react-native/Libraries/Components/View/ReactNativeStyleAttributes'
import { auth, firebase } from './firebase'
import { userContext } from './UserContext'
import AsyncStorage from '#react-native-async-storage/async-storage';
const SignIn = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const navigation = useNavigation()
const value = useContext(userContext);
const handleLogin = async() => {
await auth
.signInWithEmailAndPassword(email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with:', user.email);
getUser(user.email);
navigation.replace("Home");
})
.catch(error => alert(error.message))
}
const getUser = async (email2) => {
await firebase.database().ref().child('users').orderByChild('email').equalTo(email2).once('value').then((data) => {
data.forEach((node) => {
storeUser(node.val().username); // one data
}
)
}
)
}
const storeUser = async(data) => {
try{
await AsyncStorage.setItem('sertacKul', data);
}catch(err){
console.log(err);
}
}
return(
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<View style={styles.inputContainer}>
<Image style={styles.logo} source={require('./img/logo.png')}>
</Image>
<TextInput
placeholder="Email"
value={email}
onChangeText={text => setEmail(text)}
style={styles.input}
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={text => setPassword(text)}
style={styles.input}
secureTextEntry
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={handleLogin}
style={styles.button}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => navigation.navigate('SignUp')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Register</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => value.setData('ebebbebebe')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>{value.lastUser}</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
}
export default SignIn;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor : 'white'
},
logo :{
resizeMode :'contain',
width: '100%',
marginBottom : 40
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: '#eeeeee',
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#06d6cc',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: 'white',
marginTop: 5,
borderColor: '#06d6cc',
borderWidth: 2,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#06d6cc',
fontWeight: '700',
fontSize: 16,
},
})
Contact.js code
import React, { useState, useEffect, useContext } from "react";
import {
StyleSheet,
View,
TextInput,Text
} from "react-native";
import { auth, firebase } from "./firebase";
import { List, Avatar, Divider, FAB } from "react-native-paper";
import uuid from "react-native-uuid";
import moment from "moment";
import { userContext } from "./UserContext";
import AsyncStorage from '#react-native-async-storage/async-storage';
const Contacts = () => {
const [username, setUsername] = useState("");
const value = useContext(userContext);
const [contactList, setContactList] = useState([{}]);
const [lastUser, setLastUser] = useState('');
useEffect(() => {
setContactList([])
updateLastUserName();
getContacts();
}, [])
useEffect(() => {
console.log(lastUser);
console.log(contactList);
}, [lastUser, contactList]);
async function updateLastUserName(){
const user = await getUserName();
setLastUser(user);
}
async function getUserName(){
const user = await AsyncStorage.getItem('sertacKul');
return user;
}
const addFriend = () => {
console.log(value.lastUser)
firebase
.database()
.ref("/users/")
.once("value")
.then((data) => {
let id = uuid.v4();
firebase
.database()
.ref("/friendrelations/" + id)
.set({
id: id,
user1: username,
user2: lastUser,
relationtype: "normal",
createdDate: moment().format("DD/MM/YYYY HH:mm:ss"),
})
.then(() => alert("Friend added."));
});
};
async function getContacts(){
await firebase.database().ref().child('friendrelations').orderByChild('user2').equalTo(lastUser)
.once('value').then(data => {
data.forEach((node) => { setContactList(lastContacts => [...lastContacts, node.val().user1])})
})
}
return (
<View>
<TextInput
placeholder="Yeni Arkadaş"
value={username}
style={styles.input}
onChangeText={(text) => setUsername(text)}
/>
<FAB
onPress={() => addFriend()}
icon="plus"
style={{ position: "absolute", right: 16 }}
/>
{/* is not working */}
{contactList.map((item)=>{
(<List.Item onPress={() => navigation.navigate('Conversation')} title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
)
})}
<Divider inset/>
</View>
);
};
export default Contacts;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
},
logo: {
resizeMode: "contain",
width: "100%",
marginBottom: 40,
},
inputContainer: {
width: "80%",
},
input: {
backgroundColor: "#eeeeee",
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: "60%",
justifyContent: "center",
alignItems: "center",
marginTop: 40,
},
button: {
backgroundColor: "#06d6cc",
width: "100%",
padding: 15,
borderRadius: 10,
alignItems: "center",
},
buttonOutline: {
backgroundColor: "white",
marginTop: 5,
borderColor: "#06d6cc",
borderWidth: 2,
},
buttonText: {
color: "white",
fontWeight: "700",
fontSize: 16,
},
buttonOutlineText: {
color: "#06d6cc",
fontWeight: "700",
fontSize: 16,
},
});
The arrow function has a function body and neglects to return any value that is being mapped to. Don't forget to also specify a unique React key for the mapped components/elements.
{contactList.map((item) => {
return (
<List.Item
key={item.id}
onPress={() => navigation.navigate('Conversation')}
title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
);
})}
Or remove the body so there's an implicit return.
{contactList.map((item) => (
<List.Item
key={item.id}
onPress={() => navigation.navigate('Conversation')}
title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
))}

Why useState is not working in React Native? [duplicate]

This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 10 months ago.
I am getting an error that I do not understand in the application I developed in React Native Expo. The error is as follows; In asyncstorage I keep the name of the user logged into the application. But when I try to set it while the page is loading (useEffect), setLastUser doesn't work. When I do CTRL+S on the keyboard while trying on the same page, I get the following output.
Prev CTRL+S
After CTRL+S
Can you help me? Thanks.
App.js Code
import { StatusBar } from 'expo-status-bar';
import React, { useState, useMemo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import SignIn from './SignIn';
import SignUp from './SignUp';
import Conversation from './Conversation';
import Contacts from './Contacts';
import Settings from './Settings';
import Chats from './Chats';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {Ionicons} from '#expo/vector-icons'
import { UserProvider } from './UserContext';
import { LogBox } from "react-native"
const Stack = createNativeStackNavigator();
const Tabs = createBottomTabNavigator();
const TabsNavigator = () => (
<Tabs.Navigator screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
return <Ionicons name={route.name === "Chats" ? "chatbubble-ellipses-outline" : route.name === "Contacts" ? "people-outline" : "settings-outline"} color={color} size={size} />
}})}>
<Tabs.Screen name="Chats" component={Chats} />
<Tabs.Screen name="Contacts" component={Contacts} />
<Tabs.Screen name="Settings" component={Settings} />
</Tabs.Navigator>
);
export default function App() {
LogBox.ignoreAllLogs(true);
// const [lastUser, setLastUser] = useState('none');
// const value = useMemo(
// () => ({ lastUser, setLastUser }),
// [lastUser]
// );
return (
<UserProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen options={{headerShown : false }} name="SignIn" component={SignIn} />
<Stack.Screen
name="SignUp"
component={SignUp}
options={{ headerTitle:'Login', headerBackVisible : true, headerBackTitleVisible :true}}
/>
<Stack.Screen name="Home" component={TabsNavigator} options={{headerShown : false, headerBackTitleVisible : false}}/>
<Stack.Screen name="Contacts" component={Contacts} options={{ headerTitle:'ChatApp'}}/>
<Stack.Screen name="Conversation" component={Conversation} options={{ headerTitle:'ChatApp'}}/>
</Stack.Navigator>
</NavigationContainer>
</UserProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
SignIn.js code
import { useNavigation } from '#react-navigation/core'
import React, { useEffect, useState, createContext, useContext } from 'react'
import { KeyboardAvoidingView, StyleSheet, Text, TextInput, TouchableOpacity, View, Image } from 'react-native'
import { borderColor } from 'react-native/Libraries/Components/View/ReactNativeStyleAttributes'
import { auth, firebase } from './firebase'
import { userContext } from './UserContext'
import AsyncStorage from '#react-native-async-storage/async-storage';
const SignIn = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const navigation = useNavigation()
const value = useContext(userContext);
const handleLogin = async() => {
await auth
.signInWithEmailAndPassword(email, password)
.then(userCredentials => {
const user = userCredentials.user;
console.log('Logged in with:', user.email);
getUser(user.email);
navigation.replace("Home");
})
.catch(error => alert(error.message))
}
const getUser = async (email2) => {
await firebase.database().ref().child('users').orderByChild('email').equalTo(email2).once('value').then((data) => {
data.forEach((node) => {
storeUser(node.val().username); // one data
}
)
}
)
}
const storeUser = async(data) => {
try{
await AsyncStorage.setItem('sertacKul', data);
}catch(err){
console.log(err);
}
}
return(
<KeyboardAvoidingView
style={styles.container}
behavior="padding"
>
<View style={styles.inputContainer}>
<Image style={styles.logo} source={require('./img/logo.png')}>
</Image>
<TextInput
placeholder="Email"
value={email}
onChangeText={text => setEmail(text)}
style={styles.input}
/>
<TextInput
placeholder="Password"
value={password}
onChangeText={text => setPassword(text)}
style={styles.input}
secureTextEntry
/>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={handleLogin}
style={styles.button}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => navigation.navigate('SignUp')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>Register</Text>
</TouchableOpacity>
<TouchableOpacity
//onPress={handleSignUp}
onPress={() => value.setData('ebebbebebe')}
style={[styles.button, styles.buttonOutline]}
>
<Text style={styles.buttonOutlineText}>{value.lastUser}</Text>
</TouchableOpacity>
</View>
</KeyboardAvoidingView>
)
}
export default SignIn;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor : 'white'
},
logo :{
resizeMode :'contain',
width: '100%',
marginBottom : 40
},
inputContainer: {
width: '80%'
},
input: {
backgroundColor: '#eeeeee',
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: '60%',
justifyContent: 'center',
alignItems: 'center',
marginTop: 40,
},
button: {
backgroundColor: '#06d6cc',
width: '100%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
},
buttonOutline: {
backgroundColor: 'white',
marginTop: 5,
borderColor: '#06d6cc',
borderWidth: 2,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
buttonOutlineText: {
color: '#06d6cc',
fontWeight: '700',
fontSize: 16,
},
})
Contact.js code
import React, { useState, useEffect, useContext } from "react";
import {
StyleSheet,
View,
TextInput,Text
} from "react-native";
import { auth, firebase } from "./firebase";
import { List, Avatar, Divider, FAB } from "react-native-paper";
import uuid from "react-native-uuid";
import moment from "moment";
import { userContext } from "./UserContext";
import AsyncStorage from '#react-native-async-storage/async-storage';
const Contacts = () => {
const [username, setUsername] = useState("");
const value = useContext(userContext);
const [contactList, setContactList] = useState([{}]);
const [lastUser, setLastUser] = useState('');
useEffect(() => {
setContactList([])
setLastUser(() => getUserName()) // ıs not work
console.log('deneme',lastUser)
getContacts();
}, [])
async function getUserName(){
let user = await AsyncStorage.getItem('sertacKul');
return user;
}
const addFriend = () => {
console.log(value.lastUser)
firebase
.database()
.ref("/users/")
.once("value")
.then((data) => {
let id = uuid.v4();
firebase
.database()
.ref("/friendrelations/" + id)
.set({
id: id,
user1: username,
user2: lastUser,
relationtype: "normal",
createdDate: moment().format("DD/MM/YYYY HH:mm:ss"),
})
.then(() => alert("Friend added."));
});
};
const getContacts = async() => {await firebase.database().ref().child('friendrelations').orderByChild('user2').equalTo(() => getUserName())
.once('value').then(data => {
data.forEach((node) => { setContactList(lastContacts => [...lastContacts, node.val().user1])})
})}
return (
<View>
<TextInput
placeholder="Yeni Arkadaş"
value={username}
style={styles.input}
onChangeText={(text) => setUsername(text)}
/>
<FAB
onPress={() => addFriend()}
icon="plus"
style={{ position: "absolute", right: 16 }}
/>
{/*
BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI BURASI
{contactList && contactList.map((item)=>{
return( <List.Item onPress={() => navigation.navigate('Conversation')} title={item}
left={() => <Avatar.Image source={require('./img/profile1.png')} size={53}/>}
/>
)
})} */}
<Divider inset/>
</View>
);
};
export default Contacts;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "white",
},
logo: {
resizeMode: "contain",
width: "100%",
marginBottom: 40,
},
inputContainer: {
width: "80%",
},
input: {
backgroundColor: "#eeeeee",
paddingHorizontal: 15,
paddingVertical: 10,
borderRadius: 10,
marginTop: 5,
},
buttonContainer: {
width: "60%",
justifyContent: "center",
alignItems: "center",
marginTop: 40,
},
button: {
backgroundColor: "#06d6cc",
width: "100%",
padding: 15,
borderRadius: 10,
alignItems: "center",
},
buttonOutline: {
backgroundColor: "white",
marginTop: 5,
borderColor: "#06d6cc",
borderWidth: 2,
},
buttonText: {
color: "white",
fontWeight: "700",
fontSize: 16,
},
buttonOutlineText: {
color: "#06d6cc",
fontWeight: "700",
fontSize: 16,
},
});
You have to await the response of getUserName function. A good option is place the content of useEffect inside a async function. For example:
useEffect(() => {
setContactList([]);
updateLastUserName();
getContacts();
}, []);
useEffect(() => {
// Need to wait the lastUser state change to can use it
console.log(lastUser);
}, [lastUser]);
async function updateLastUserName(){
const username = await getUserName();
setLastUser(username);
}
async function getUserName(){
const user = await AsyncStorage.getItem('sertacKul');
return user;
}

React native - dispatching action gets me back to first screen, but it shouldnt

I'been having this odd issue for quite a while. Whenever I dispatch any of action from my context API i get send back to the first screen in Stack Navigation (expo react native).
Is there a way to fix this ?
Files:
context.js
import { createContext } from 'react';
export const AppContext = createContext();
App.js
export default function App() {
const Stack = createNativeStackNavigator();
// GLOBAL STATE
const [alarms, setAlarms] = useState([]);
const dispatchAlarmEvent = (actionType, payload) => {
switch (actionType) {
case 'ADD_ALARM':
setAlarms([ ...alarms, payload ]);
break; // return;
case 'REMOVE_ALARM':
setAlarms([...alarms.filter(alarm => alarm.id !== payload.id)]);
break; // return;
case 'EDIT_ALARM':
setAlarms([...alarms.filter(alarm => alarm.id !== payload.id), payload]);
break; // return;
default:
break; // return;
}
};
const log = (x)=> console.log(x)
return (
<AppContext.Provider value={ { alarms , dispatchAlarmEvent, log} }>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Start" component={Start} options={{
headerShown: false,
title: 'Start',
}} />
<Stack.Screen name="Home" component={Home} options={{
headerStyle: { backgroundColor: Theme.primary },
headerTintColor: 'rgb(243,243,243)',
headerTitleStyle: { fontWeight: 'bold' },
title: 'Alarms List',
}} />
<Stack.Screen name="AddAlarm" component={AddAlarmForm} options={{
headerStyle: { backgroundColor: Theme.primary },
headerTintColor: 'rgb(243,243,243)',
headerTitleStyle: { fontWeight: 'bold' },
title: 'Add Alarm',
}} />
</Stack.Navigator>
</NavigationContainer>
</AppContext.Provider>
)
}
and example of place where I dispatch action:
Item.js
const AlarmItem = (props) => {
const [isEnabled, setIsEnabled] = useState(props.ring);
const [ expanded, toggleExpanded ] = useBool(false);
const [ arrowUpyDowny, setArrowUpyDowny ] = useState(faChevronDown);
const [ height, setHeight ] = useState(new Animated.Value(0))
const { dispatchAlarmEvent } = useContext(AppContext)
const week = ["Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat.", "Sun."]
const toggle = () => {
const toPos = ( !expanded )? 140 : 0;
Animated.spring(height, {
toValue: toPos,
useNativeDriver: false,
}).start();
toggleExpanded()
}
const deleteItem = () =>{
console.log( props.id )
dispatchAlarmEvent('REMOVE_ALARM', { id: props.id });
Database.remove(props.id)
}
useEffect( ()=> {
}, [isEnabled])
return (
<View style={styles.container}>
<View style={styles.row}>
<Text style={styles.time}> { props.hours } : { props.minutes } </Text>
<Switch
trackColor={{ false: "#767577", true: Theme.primary+'5d' }}
thumbColor={isEnabled ? Theme.primary : "#f4f3f4"}
ios_backgroundColor="#3e3e3e"
onValueChange={()=> setIsEnabled(!isEnabled)}
value={isEnabled}
style={{ flex: 1 }}
/>
</View>
<View style={[styles.row, { borderTopWidth: 0 }]}>
<TouchableNativeFeedback
background={TouchableNativeFeedback.Ripple('rgba(255,255,255,1)', true)}
onPress={() => deleteItem()}
style={{
width: 60,
height: 60,
}}
>
<View style={{ margin: 10, width: 50, height: 50, background: "red", justifyContent: 'center', alignItems: 'center', backgroundColor: Theme.primary, borderRadius: 50 }}>
<FontAwesomeIcon icon={ faTrash } color={'#fff'}/>
</View>
</TouchableNativeFeedback>
<TouchableNativeFeedback
background={TouchableNativeFeedback.Ripple('rgba(255,255,255,1)', true)}
onPress={() => toggle()}
style={{
width: 60,
height: 60,
}}
>
<View style={{ margin: 10, width: 50, height: 50, background: "red", justifyContent: 'center', alignItems: 'center', backgroundColor: Theme.primary, borderRadius: 50 }}>
<FontAwesomeIcon icon={ (!expanded)? faChevronDown: faChevronUp } color={'#fff'}/>
</View>
</TouchableNativeFeedback>
</View>
<Animated.View style={{
height: height, // animowany styl, tutaj wysokość View
// backgroundColor: "#FF0000",
}} >
{
(expanded) && (<View style={styles.unfolded}>
{
props.days.map( (day,i)=> ( <TouchableNativeFeedback
key={i}
background={TouchableNativeFeedback.Ripple('rgba(255,255,255,1)', true)}
onPress={() => alert('xx')}
style={{
width: 30,
height: 30,
}}
>
<View style={{ margin: 3, width: 50, height: 50, justifyContent: 'center', alignItems: 'center', color: '#fff', backgroundColor: (day)? Theme.lighter: 'rgba(255,255,255,.3)', borderRadius: 50, }}>
<Text style={{color: '#fff'}}> { week[i] } </Text>
</View>
</TouchableNativeFeedback> ))
}
</View>)
}
</Animated.View>
</View>
)
}
Please if you have any clues? or perhaps i am doing sth wrong. Thx in advance

React navigation hide drawer item

I am using React navigation 5.
I have a settings icon in the header that routes to the Setting Screen. So i want to hide the routes from the drawer.
Here's my code.
My CustomDrawerContent i have
const newState = { ...state };
newState.routes = newState.routes.filter((item) => item.name !== "Setting");
Its render function has:
<DrawerItemList state={newState} {...props} />
still the drawer item for settings has an empty container there. When i do console.log(newState.routes) it doesn't have setting.
Entire file is below
import React, { useContext } from "react";
import { View, StyleSheet } from "react-native";
import { connect } from "react-redux";
import {
Text,
Avatar,
ThemeContext,
Button,
Divider,
SocialIcon,
Icon,
} from "react-native-elements";
import {
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from "#react-navigation/drawer";
import { signOut } from "../store/actions/authActions";
const CustomDrawerContent = (props) => {
const { theme } = useContext(ThemeContext);
const { state } = props;
const signOut = props.signOut;
const newState = { ...state };
newState.routes = newState.routes.filter((item) => item.name !== "Setting");
return (
<View style={{ flex: 1, backgroundColor: "#f5f5f5" }}>
<DrawerContentScrollView {...props}>
<View style={{ paddingVertical: 10, paddingHorizontal: 45 }}>
{/* View for profile pic area */}
<View
style={{
display: "flex",
flexDirection: "column",
marginTop: 25,
}}
>
<Avatar
size="large"
rounded={true}
icon={{ name: "rocket", color: "orange", type: "font-awesome" }}
overlayContainerStyle={{ backgroundColor: "white" }}
onPress={() => console.log("Works!")}
activeOpacity={0.7}
containerStyle={{ flex: 1 }}
/>
<Text
style={{
fontSize: 18,
fontWeight: "bold",
paddingTop: 10,
color: "#555",
}}
>
Olivia Groza
</Text>
<Text style={theme.Text.captionStyles}>#Govliva</Text>
<Button title="Go Pro" containerStyle={{ marginTop: 10 }}></Button>
</View>
</View>
<Divider
style={{ margin: 10, backgroundColor: "#dddddd", height: 1 }}
></Divider>
{console.log(newState.routes)}
<DrawerItemList state={newState} {...props} />
<DrawerItem
icon={({ color, size }) => (
<Icon name="home" type="material-community" color={color} />
)}
label="Logout"
onPress={signOut}
/>
</DrawerContentScrollView>
<View style={styles.shareContainer}>
<SocialIcon type="twitter" iconSize={18} style={styles.iconContainer} />
<SocialIcon
type="facebook"
iconSize={18}
style={styles.iconContainer}
/>
<SocialIcon
type="instagram"
iconSize={18}
style={styles.iconContainer}
/>
</View>
</View>
// <DrawerContentScrollView {...props}>
// <DrawerItemList {...props} />
// <Text>adfafsd</Text>
// </DrawerContentScrollView>
);
};
const styles = StyleSheet.create({
shareContainer: {
paddingHorizontal: 10,
display: "flex",
flexDirection: "row",
// justifyContent: "center"
},
iconContainer: {
height: 40,
width: 40,
},
});
const mapStateToProps = (state) => {
return {};
};
const mapDispathToProps = (dispatch) => {
return {
signOut: () => dispatch(signOut()),
};
};
export default connect(mapStateToProps, mapDispathToProps)(CustomDrawerContent);

console.error:"the action navigate with payload...was not handled..."

I'm having an issue with the "onLogin" function within the "LoginComponent". After pressing the TouchableOpacity that handles that function, I want the user to then be directed to the "HomeComponent", but instead I get this console.error: "the action navigate with payload...was not handled..." Anybody know why this is? Any help would be greatly appreciated. Thanks!
import React, { Component } from 'react';
import 'react-native-gesture-handler';
import { createStackNavigator } from '#react-navigation/stack';
import WelcomeScreen from './WelcomeComponent';
import LoginScreen from './LoginComponent';
import RegisterScreen from './RegisterComponent';
import HomeScreen from './HomeComponent';
import { NavigationContainer } from '#react-navigation/native';
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs';
import { AsyncStorage } from 'react-native';
const AuthStack = createStackNavigator();
const AuthStackScreen = () => {
return <AuthStack.Navigator initialRouteName="Welcome">
<AuthStack.Screen name="Welcome" component={WelcomeScreen} />
<AuthStack.Screen name="Login" component={LoginScreen} />
<AuthStack.Screen name="Register" component={RegisterScreen} />
</AuthStack.Navigator>
};
const HomeTab = createMaterialBottomTabNavigator();
const HomeTabScreen = () => {
return <HomeTab.Navigator initialRouteName="Home">
<HomeTab.Screen name="Home" component={HomeScreen} />
</HomeTab.Navigator>
}
class Navigation extends Component {
constructor(props) {
super(props);
this.state = {
isLoggedIn: false,
};
this.loginStatusCheck();
}
loginStatusCheck = async () => {
const userToken = await AsyncStorage.getItem("userprofile");
if(userToken) {
this.setState({ isLoggedIn: true })
} else {
this.setState({ isLoggedIn: false })
}
}
render() {
return(
<NavigationContainer>
{this.state.isLoggedIn ? <AuthStackScreen /> : <HomeTabScreen />}
</NavigationContainer>
);
};
};
export default Navigation;
import React, { Component } from 'react';
import { StyleSheet, SafeAreaView, ScrollView, View, TouchableOpacity, Text, Linking, AsyncStorage } from 'react-native';
import { Input, CheckBox } from 'react-native-elements';
import { FontAwesome } from '#expo/vector-icons';
class LoginScreen extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password:"",
token: "",
remember: false
};
this.getData();
};
handleUsernameChange = username => {
this.setState({ username })
};
handlePasswordChange = password => {
this.setState({ password })
};
onLogin = async () => {
try {
await AsyncStorage.setItem("userprofile", JSON.stringify({ username: this.state.username, password: this.state.password }));
this.props.navigation.navigate("Home", {
screen: "HomeScreen",
});
} catch (err) {
console.log(err);
}
};
getData = async () => {
try {
const userprofile = await AsyncStorage.getItem("userprofile");
const userProfile = JSON.parse(userprofile);
if (userProfile !== null) {
this.setState({ ...userProfile })
}
if (username !== null) {
this.setState({ username })
}
if (password !== null) {
this.setState({ password })
}
} catch (err) {
console.log(err);
}
}
render() {
const { username, password } = this.state;
return (
<SafeAreaView style={styles.container}>
<ScrollView>
<Text style={styles.titleText}>Login</Text>
<Text style={styles.fillerText}>Hi there! Nice to see you again.</Text>
<Input
inputStyle={{color: 'white'}}
placeholder="Enter username"
onChangeText={this.handleUsernameChange}
value={username}
keyboardType="email-address"
autoCapitalize="none"
leftIcon={{ type: 'font-awesome', name: 'user-circle-o', color: 'white', marginRight: 10 }}
/>
<Input
inputStyle={{color: 'white'}}
placeholder="Password"
secureTextEntry
onChangeText={this.handlePasswordChange}
value={password}
leftIcon={{ type: 'font-awesome', name: 'lock', color: 'white', marginRight: 10 }}
/>
<CheckBox
title="Remember Me"
checked={this.state.remember}
onPress={() => this.setState({remember: !this.state.remember})}
containerStyle={styles.rememberCheckbox}
textStyle={{color: 'white'}}
checkedColor="crimson"
/>
<TouchableOpacity
style={styles.loginButton}
title="Login" type="submit"
onPress={this.onLogin}
>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<Text style={{textAlign: 'center', color: 'grey', marginTop: 20}}>
OR use an account from one of the following:
</Text>
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.twitterButton}>
<FontAwesome name="twitter" color="white" style={{marginRight: 5}}/>
<Text style={{color: 'white'}}>Twitter</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.facebookButton}>
<FontAwesome name="facebook-square" color="white" style={{marginRight: 5}}/>
<Text style={{color: 'white'}}>Facebook</Text>
</TouchableOpacity>
</View>
<View style={{alignItems: 'center'}}>
<TouchableOpacity style={styles.googleButton}>
<FontAwesome name="google" color="black" style={{marginRight: 5}}/>
<Text style={{color: 'grey'}}>Google</Text>
</TouchableOpacity>
</View>
<View style={styles.linkContainer}>
<TouchableOpacity style={{marginTop: 75}} onPress={() => Linking.openURL('#')}>
<Text style={{color: 'white'}}>
Forgot Your Password?
</Text>
</TouchableOpacity>
<TouchableOpacity style={{marginTop: 75, marginLeft: 210}} onPress={() => Linking.openURL('#')}>
<Text style={{color: 'white'}}>
Register
</Text>
</TouchableOpacity>
</View>
</ScrollView>
</SafeAreaView>
);
};
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: 'black'
},
buttonsContainer: {
flex: 2,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row'
},
linkContainer: {
flex: 3,
justifyContent: 'center',
flexDirection: 'row'
},
titleText: {
fontSize: 26,
color: 'white',
marginBottom: 30,
marginTop: 20
},
fillerText: {
color: 'grey',
marginBottom: 20
},
loginButton: {
backgroundColor: 'crimson',
paddingVertical: 17,
paddingHorizontal: 25,
borderRadius: 20,
textAlign: 'center'
},
buttonText: {
color: 'white',
fontSize: 18,
textAlign: 'center'
},
twitterButton: {
backgroundColor: '#00acee',
marginTop: 20,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
width: '40%',
marginLeft: 20,
flexDirection: 'row',
borderRadius: 20
},
facebookButton: {
backgroundColor: '#4267B2',
marginTop: 20,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
width: '40%',
marginLeft: 20,
flexDirection: 'row',
borderRadius: 20
},
googleButton: {
backgroundColor: '#FFFFFF',
marginTop: 20,
padding: 10,
justifyContent: 'center',
alignItems: 'center',
width: '40%',
marginLeft: 20,
flexDirection: 'row',
borderRadius: 20
},
rememberCheckbox: {
margin: 10,
marginBottom: 20,
backgroundColor: null
}
});
export default LoginScreen;
I don't think its necessary to use navigate in your LoginScreen component, since you've already written code that conditionally renders two navigators based on the value of isLoggedIn.
What you're missing in your current implementation is a way to update isLoggedIn from within your LoginScreen component. Then if isLoggedIn is updated and set to true, the Navigation component will be re-rendered and the HomeScreen component is shown without having to navigate.
I've chosen to use react context here, but you could also use this approach with something like redux also if you prefer that. The reason to use something like react context is to be able to easily pass isLoggedIn and its setter between components.
I'll give a more general example, because its easier to illustrate the approach that way:
// Imports and other stuff...
const LoginContext = React.createContext([null, () => {}]);
const LoginContextProvider = props => {
const [isLoggedIn, setIsLoggedIn] = React.useState(false);
return (
<LoginContext.Provider value={[isLoggedIn, setIsLoggedIn]}>
{props.children}
</LoginContext.Provider>
);
};
const HomeScreen = () => {
return (
<View>
<Text>HomeScreen</Text>
</View>
);
};
const LoginScreen = () => {
const [isLoggedIn, setIsLoggedIn] = React.useContext(LoginContext);
return (
<View>
<Text>LoginScreen</Text>
<Button
title="login"
onPress={() => {
setIsLoggedIn(true);
}}
/>
</View>
);
};
const HomeTabScreen = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
</Tab.Navigator>
);
};
const AuthStackScreen = ({ navigation }) => {
return (
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
</Stack.Navigator>
);
};
const Navigation = () => {
const [isLoggedIn, setIsLoggedIn] = React.useContext(LoginContext);
return (
<NavigationContainer>
{isLoggedIn ? <HomeTabScreen /> : <AuthStackScreen />}
</NavigationContainer>
);
};
export default function App() {
return (
<LoginContextProvider>
<Navigation />
</LoginContextProvider>
);
}
So the approach shown above is to create a provider that holds your isLoggedIn state and setter (setIsLoggedIn). Then when we wrap Navigation with this provider so we can access isLogged and setIsLoggedIn from any component inside the provider, allowing us to update the isLogged state inside the LoginScreen component. When this state updates, the provider and everything inside it (i.e. Navigation), will re-render and show the HomeScreen component.
Normally the convention is to put most the react context related stuff in its own file and import parts in components where you need them, but for demonstration purposes I haven't done this.

Resources