Using Custom (Google) Fonts in React-Native (Expo)

Using Custom (Google) Fonts in React-Native (Expo)

ยท

6 min read

Introduction

Injecting more brand personality into our mobile app is something mobile developers come across more often as a project might require you to build their app using a particular font. Also, if you are looking to create a consistent experience for your users, then you will want to use your own hand picked font. In this article, we will be learning how to inject custom fonts in our react-native expo project and refactoring the font implementation to apply for the whole project . For using custom font in react-native cli, you can check this Link to my article where I explained it as well.

1. Setting up the Project

We start off by creating a react-native project in expo using this command:

 expo init expo-custom-fonts

Then we can choose the template we want to use which is the first one and wait for the process to complete.

Now that the process is complete we can run our project using

  expo start

This will start up a development server for us where we can run our project on ios and android by pressing 'i' or 'a' respectively in the Metro development server.

image.png

image.png

Now this is how our screen looks like displaying the 'ExpoFont' text in our App.js file.

2. Using the Custom Fonts

We will be using Google Fonts as expo has a first-class support for all fonts that are listed on Google Fonts. We will be using the font called Dancing Script in this project.

To use the Dancing Script Fonts, we will install the font-npm-package package using the command below:

expo install @expo-google-fonts/dancing-script

3. AppLoading Components

After installation, then we can integrate this font in our app. But before that, we will be introducing a component called into our project as well. This is useful because, the fonts are not going to be ready right away when the app starts loading, so it is recommended to not render anything on the UI until the font is loaded and ready to be displayed.

To use this component we will need to install the expo-app-loading package using this command:

 expo install  expo-app-loading

Once this is installed we can then make use of it in our ExpoFont component like this:

import AppLoading from "expo-app-loading";

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

What this does is, it tell the application that if our custom font (Dancing Script) has not loaded yet, return AppLoading and do not display anything on the UI screen until the font is loaded.

4. useFont Hook

Now we are ready to integrate our DancingScript font to our app. We will using the useFont hook.

import {
  useFonts,
  DancingScript_400Regular,
  DancingScript_500Medium,
  DancingScript_600SemiBold,
  DancingScript_700Bold,
} from "@expo-google-fonts/dancing-script";

 let [fontsLoaded] = useFonts({
    DancingScript_400Regular,
    DancingScript_500Medium,
    DancingScript_600SemiBold,
    DancingScript_700Bold,
  });

Then we can Add the Font Family name to the text element inside the ExpoFont Component. The overall code will look like:

import React from "react";
import { View, Text, StyleSheet } from "react-native";
import AppLoading from "expo-app-loading";
import {
  useFonts,
  DancingScript_400Regular,
  DancingScript_500Medium,
  DancingScript_600SemiBold,
  DancingScript_700Bold,
} from "@expo-google-fonts/dancing-script";

const Expofont = () => {
  let [fontsLoaded] = useFonts({
    DancingScript_400Regular,
    DancingScript_500Medium,
    DancingScript_600SemiBold,
    DancingScript_700Bold,
  });

  if (!fontsLoaded) {
    return <AppLoading />;
  }
  return (
    <View>
      <Text style={styles.text}>Expofont</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  text: {
    fontFamily: "DancingScript_500Medium",
  },
});
export default Expofont;

And we have an output of:

image.png

image.png

But you'll agree with me that this method is not an efficient way of working on a large expo project. Say you have to use three different fonts, the App.js becomes messed up trying to import all fonts in there to use. Additionally, there are cases where the styles does not apply to all the components of your project, i.e the font only works on App.js file.

5. Refactoring

We'll create a folder called hooks and inside this folder, we will have a file named useFont.js which will hold all the custom fonts we will be using throughout our project.

We will be testing with three different fonts: Oxanium, Poppins, WorkSans. Go to Google Fonts Website, search for these fonts and click on download family to download them. After you finish downloading you can then extract the fonts file (.tff) from the zip file and move it to the asset/fonts directory as shown below:

image.png

Now we will create a component folder and have three components: Oxanium.js, Poppins.js, WorkSans.js

Inside the useFont.js we will write

import * as Font from "expo-font";

export const useFonts = async () => {
  await Font.loadAsync({
    OxaniumBold: require("../assets/fonts/Oxanium/Oxanium-Bold.ttf"),
    PoppinsRegular: require("../assets/fonts/Poppins/Poppins-Regular.ttf"),
    WorkSansRegular: require("../assets/fonts/WorkSans/WorkSans-Regular.ttf"),
  });
};
  • The expo-font-package provides us with the loadAsync method which will help us add the fonts.

  • The App Loading components keeps the application loading open until the fonts gets loaded to be displayed.

Then we will load our components in the App.js file by importing the useFont hook:


import { StyleSheet, Text, View } from "react-native";
import React, { useState } from "react";
import Oxanium from "./components/Oxanium";
import AppLoading from "expo-app-loading";
import { useFonts } from "./hooks/useFonts";
import Poppins from "./components/Poppins";
import WorkSans from "./components/WorkSans";

const App = () => {
  //setting the initial loading to false
  const [isLoading, setIsLoading] = useState(false);

  // loading the fonts
  const LoadFonts = async () => {
    await useFonts();
  };

  if (!isLoading) {
    return (
      // if the font is not loaded return AppLoading
      <AppLoading
        startAsync={LoadFonts}
        onFinish={() => setIsLoading(true)}
        onError={() => {}}
      />
    );
  }
  return (
    <View style={styles.container}>
      <Oxanium />
      <Poppins />
      <WorkSans />
    </View>
  );
};

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});
  1. We set a state to check and update our loaded fonts coming from the useFont hook.

  2. The LoadFonts function is aynchronous, meaning it takes time to be completed(to load our fonts).

  3. Then we do a conditional check, if the isLoading is false and has not load, then we are returning an AppLoading component that will start the LoadFonts helper function asynchronously using (startAsync={LoadFonts}). Once the fonts get loaded onFinish={() => setIsLoading(true)} sets the state to true which will then render the component.

Sample of one of the component file: Oxanium.js (the other 2 components have the same structure as well)

import { StyleSheet, Text, View } from "react-native";
import React from "react";

const Oxanium = () => {
  return (
    <View>
      <Text style={styles.text}>Oxanium</Text>
    </View>
  );
};

export default Oxanium;

const styles = StyleSheet.create({
  text: {
    fontFamily: "OxaniumBold",
    fontSize: 40,
  },
});

Now we can see our output and how we can use these fonts throughout our project.

image.png

Conclusion

Thank you for reading and hope you have learnt a new stuff in the usage of custom fonts in an expo app. You can check out the final code in my github repo here.