Using Custom Fonts in Expo : The Best Way

Piyush Gupta
2 min readMar 3, 2018

--

Assuming that you have created an expo project or npm installed expo SDK and using Redux state Management.

The first step is to load the custom font in the Root component . now if you are using React Navigation / RNRF , you should probably load the fonts in Router.js where all the Navigators exists and render method returns a StackNavigator or TabNavigator . if not using any navigation please do the loading stuff in Root Component.

Font is a Module in the Expo SDK which will help us . Now, we can load font using Font.loadAsync() function in componentDidMount() lifeCycle Method of Router.js . since this is an Asynchronous Task , we have to use async and await , to do other stuff whenever the await statement finishes .just like this :

import { Font } from 'expo';class Router extends Component{async componentDidMount() {
await Font.loadAsync({
// 'any_name' : require('path_to_your_font_file')
'font1': require('../assets/Quicksand-Regular.ttf'),
'font2': require('../assets/sans.ttf'),
});
// other stuff
}render(){
return (
<RootStack />
)
}
}
// RootStack defined here

Now after the font is loaded we have to change the value of boolean variable fontLoaded in the Redux State to true .

so we have to create an ActionCreator and a Reducer . I wont explain anything about this , you can check this to learn about redux : https://medium.com/@jonlebensold/getting-started-with-react-native-redux-2b01408c0053

so let our Action creator be named as fontLoader() which you can call just after await (Font.loadAsync) statement and which will set the value of fontLoaded to be true in the redux state .

async componentDidMount() {
await Font.loadAsync({
'font1': require('../assets/Quicksand-Regular.ttf'),
'font2': require('../assets/sans.ttf'),
});

this.props.fontLoader();
}

Now we have successfully loaded the font and we know about it . you can just check if fontLoaded is true and return the Text with custom fontFamily style:

if(fontLoaded)
return <Text style={{ fontFamily: 'font1' }}> my text </Text>

Optional (But Efficient):

Instead of connecting to Redux and using fontLoaded (which takes time )in each Component where you use Text with font , you can make a FontText Component which takes care of all and you can implement it everywhere .

FontText.js

import { Text } from 'react-native' ;
import React, { Component } from 'react' ;
import { connect } from 'react-redux' ;
class FontText extends Component {Loadtext(){
if(this.props.fontLoaded){
return (<Text style={this.props.style}>{this.props.children}</Text>) ;
}
}
render(){
return (
this.Loadtext()
);
}
}
const mapStateToProps = (state) => {
const {fontLoaded}= state.loader;
return { fontLoaded };
};
export default connect(mapStateToProps ,{})(FontText) ;

Now, whenever you want to use Text with custom font , use FontText instead

import FontText from './FontText';
.....
<FontText style={{ fontFamily: 'font2'}}>Hello World</FontText>

Hope this Helps . Happy Coding :)

--

--