Using Custom Fonts with Expo

Using Custom Fonts with Expo

ยท

3 min read

There's nothing wrong with Android's native sytem fonts, they're perfectly readable and people are used to their look, but in order to give your App some unique character, you probably want to include custom fonts.

It'll take a short while until these fonts are available and ready, so in the meantime, you can use Expo's <AppLoading /> component:


๐Ÿ“ฑ Expo AppLoading

Expo AppLoading is a component that keeps the splash screen until all assets are loaded. In its simplest usage, your top level App component would conditionally render either <AppLoading /> or the actual App components.

To install:

expo install expo-app-loading

To import:

import AppLoading from 'expo-app-loading';

See examples for usage below.


๐Ÿ“ฑ Using Expo Google Fonts

Expo supports an easy way to include Google Fonts with their expo-google-fonts package. You can import them directly by specifying the font family (check the Full list of supported Google fonts to see which exact name to use). For this example, I'm using the Lobster font (Lobster_400Regular).

First step is to install it:

expo install @expo-google-fonts/lobster

In App.js, you can import it and use the useFonts hook to detect when it's loaded:

import AppLoading from 'expo-app-loading';
import { StyleSheet, View, Text } from 'react-native';
import { useFonts, Lobster_400Regular } from '@expo-google-fonts/lobster';

export default function App(){
  let [fontsLoaded] = useFonts({ Lobster_400Regular })

  if (!fontsLoaded) {
    return (
      <AppLoading />
    );
  }

  return (
    <View>
      <Text style={{ fontFamily: 'Lobster_400Regular' }}>I am the Lobster Font</Text>
    </View>
  )
}

๐Ÿ“ฑ Loading a custom font (with useFonts hook)

To load your own font file (supported formats are .otf and .ttf), put them into a folder inside your project (for example, /assets/fonts).

First, install expo-font:

expo install expo-font

Then in App.js, use the useFonts hook to require the file. I've given it a name lobster-reg, which is the name that's used to refer to it in the StyleSheet.

import AppLoading from 'expo-app-loading';
import { StyleSheet, View, Text } from 'react-native';
import { useFonts } from 'expo-font';

export default function App(){
  let [fontsLoaded] = useFonts({ 'lobster-reg': require('./assets/fonts/Lobster-Regular.ttf') })

  if (!fontsLoaded) {
    return (
      <AppLoading />
    );
  }

  return (
    <View>
      <Text style={{ fontFamily: 'lobster-reg' }}>I am the Lobster Font</Text>
    </View>
  )
}

๐Ÿ“ฑ Loading a custom font (with Font.loadAsync)

useFonts is a quick-and-uncomplicated way to load fonts, but Font.loadAsync gives a little more control. You'll also need it if you're still into Class components.

To load the font, write a small function fetchFonts and pass it as startAsync prop to the <AppLoading /> component. The onFinish prop can then set the state of fontsLoaded.

import AppLoading from 'expo-app-loading';
import { useState } from 'react';
import * as Font from 'expo-font';

// function to load the font(s)
const fetchFonts = () => {
  return Font.loadAsync({
     'lobster-reg': require('./assets/fonts/Lobster-Regular.ttf')
  });
};

export default function App(){
  // keep the value of fontsLoaded in state
  const [ fontsLoaded, setFontsLoaded ] = useState(false);


  if (!fontsLoaded) {
    return (
      <AppLoading
        startAsync={fetchFonts}
        onError={console.warn}
        onFinish={() => setFontsLoaded(true)}
      />
    );
  }


  return (
    <View>
      <Text style={{ fontFamily: 'lobser-reg' }}>I am the Lobster Font</Text>
    </View>
  )
}

Those were three (slightly different) ways to include a custom font. I can't say which way I prefer, the differences are subtle. The only sure thing is that you always want to include them in the app bundle assets, instead of downloading them from the web.


๐Ÿ“ฑ Thanks for reading!

If you find any errors or have additions, questions or just want to say hi, please leave a comment below, or get in touch via my website jsdisco.dev or Twitter.
Keep calm & code ๐Ÿ‘‹