How to use custom font in React Native

Recently I started learning React Native to make a mobile application for my research. At first, I planned to use SwiftUI, but it turned out that SwiftUI is still in its early stage and will have many changes in the next updates. So I decided to use React Native for building both iOS and Anroid application.

By default, React native application uses the default font, but fortunately use can use custom fonts like Google fonts too.

In this example, I will use a blank application created with expo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>My App</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    fontSize: 40
  }
});

Since we haven’t use any custom font, our app on Android will look like this.

My App

Let’s try assigning IndieFlower-Regular font to our title

Step 1: Create a /assets/fonts folder in our app’s root.

Step 2: Put the font file IndieFlower-Regular.ttf into created folder.

Step 3: Import the loadAsync function from expo-font package.

1
import {loadAsync} from 'expo-font'

Step 4: Define a function to load our font.

1
2
3
4
5
const loadFonts = () => {
  return loadAsync({
    "indie-flower": require('./assets/fonts/IndieFlower-Regular.ttf')
  });
};

loadAsync function will return a Promise so our loadFonts function will return a Promise too.

Step 5: Use the useState hook to observe if our font has been loaded or not

1
import { useState } from "react"
1
2
3
4
5
6
7
8
9
export default function App() {
  // use react hook to observe if font has been loaded or not
  const [isFontLoaded, setIsFontLoaded] = useState(false);
  return (
    <View style={styles.container}>
      <Text style={styles.title}>My App</Text>
    </View>
  );
}

Step 5: React Native will load our font after the application has been started, but it will take a couple of milliseconds. So we have to tell React Native to show a Loading state until our font has been loaded successfully.

1
import { AppLoading } from "expo"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
export default function App() {
  const [isFontLoaded, setIsFontLoaded] = useState(false);
  if (!isFontLoaded) {
    <AppLoading
      startAsync={loadFonts}
      onFinish={() => {
        setIsFontLoaded(true);
      }}
    ></AppLoading>;
  }
  return (
    <View style={styles.container}>
      <Text style={styles.title}>My App</Text>
    </View>
  );
}

The startAsync property of AppLoading will handle our Promise, and after finishing it will set isFontLoaded to true since we told it to do so in the onFinish property

Step 6: After that, we can simply add fontFamily: “indie-flower” to our title’s style.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    fontSize: 40,
    fontFamily: 'indie-flower'
  }
});

Finally our Application will look like this

My App

This is what our code looks like

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import React, { useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { loadAsync } from 'expo-font';
import { AppLoading } from 'expo';
const loadFonts = () => {
  return loadAsync({
    'indie-flower': require('./assets/fonts/IndieFlower-Regular.ttf')
  });
};

export default function App() {
  const [isFontLoaded, setIsFontLoaded] = useState(false);
  if (!isFontLoaded) {
    return (
      <AppLoading
        startAsync={loadFonts}
        onFinish={() => {
          setIsFontLoaded(true);
        }}
      ></AppLoading>
    );
  }
  return (
    <View style={styles.container}>
      <Text style={styles.title}>My App</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    fontSize: 40,
    fontFamily: 'indie-flower'
  }
});