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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.