expo: useFonts hook randomly failing to load fonts

Summary

When I use the {useFonts, Abel_400Regular} hook from “@expo-google-fonts/abel” and {HankenGrotesk_300} from “@expo-google-fonts/hanken-grotesk” the Abe font will fail to load on my iOS Expo Go app and my Android studio emulator. However, when I add the function

const onLayoutRootView = useCallback(async () => {
		if (fontsLoaded) {
		  await SplashScreen.hideAsync();
		}
	  }, [fontsLoaded]);

and save my editor the font loads fine. But when I reload each app from Expo Cli the font refuses to load again unless I remove the function, save in my editor, add the function, and save again. I had this issue earlier with locally saved .otf font files, so I believe the issue is with the { useFonts } hook. I’ve tried all fixes I can find online and nothing’s helped.

EDIT: I found out it’s loading the fonts whenever I hot-reload after changing any code in the render return statement for a function component. I just added an if (fontsLoaded) {} and saved and it loaded the fonts. I’m guessing it’s throwing the Font not loaded error slightly before the font gets a chance to load, but when I use a splashscreen to wait for it to load it gets stuck on the splashscreen forever.

What platform(s) does this occur on?

Android, iOS

SDK Version

~48.0.9

Environment

expo-env-info 1.0.5 environment info:
    System:
      OS: Windows 10 10.0.19044
    Binaries:
      Node: 18.13.0 - C:\Program Files\nodejs\node.EXE
      npm: 9.6.0 - C:\Program Files\nodejs\npm.CMD
    IDEs:
      Android Studio: AI-221.6008.13.2211.9619390
    npmPackages:
      @expo/webpack-config: ^18.0.1 => 18.0.2
      expo: ~48.0.9 => 48.0.9
      react: 18.2.0 => 18.2.0
      react-dom: 18.2.0 => 18.2.0
      react-native: 0.71.4 => 0.71.4
      react-native-web: ~0.18.10 => 0.18.12
    Expo Workflow: managed

Minimal reproducible example

Here is the minimum code I was able to reproduce the error with. When I change the return statement and hot-save the project, the render update fixes the font.

import React, { useCallback } from "react";
import {StyleSheet, Text} from 'react-native'
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { useFonts, Abel_400Regular } from "@expo-google-fonts/abel";
import { HankenGrotesk_300Light } from "@expo-google-fonts/hanken-grotesk";
import * as SplashScreen from "expo-splash-screen";

import HomeScreen from "./screens/HomeScreen";
import ActiveSubscriptionsScreen from "./screens/ActiveSubscriptionsScreen";
import CustomNavigationBar from "./components/CustomNavigationBar";
import LogInScreen from "./screens/LoginScreen";
import ViewOrdersScreen from "./screens/ViewOrdersScreen";
import CartScreen from "./screens/CartScreen";
import AccountScreen from "./screens/AccountScreen";
import SignUpScreen from "./screens/SignUpScreen";



export default function App() {
	const [fontsLoaded] = useFonts({
		Abel_400Regular,
		HankenGrotesk_300Light
	})

	const onLayoutRootView = useCallback(async () => {
		if (fontsLoaded) {
		  await SplashScreen.hideAsync();
		}
	  }, [fontsLoaded]);

	return (
		<Text style={{fontFamily: "Abel_400Regular", alignSelf: "center", marginTop: 500}}>Styling! :D Hooray!</Text>
	);
}

Here is one of the screens the font is running on

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 4
  • Comments: 61 (23 by maintainers)

Commits related to this issue

Most upvoted comments

After days of debugging and countless builds, we found the problem, at least in our case. The culprit, out of all things, was expo-insights. The app was stripped bare to a single, basic component and when that still didn’t work, we started removing non-essential packages until we found it.

Something within expo-insights is breaking the app startup process. In our case, when the behavior was encountered on cold app starts, it would prevent any assets (fonts, images) from being loaded and tell us that expo-updates was disabled, when it was not. After removing insights and rebuilding, we are no longer seeing the issue loading assets. This was incredibly hard to debug because there were never any errors raised even hinting that it could be related to expo-insights.

The version of expo-insights installed was 0.2.0. For what it’s worth, this was likely an iOS only issue. @douglowder, you may want to relay these findings to the expo-insights team, if you are able to.

⚠️ For anyone experiencing this issue, check if you have expo-insights installed and, if so, remove it and rebuild your app. ⚠️

This issue still happens on sdk 50

useFont will randomly return false for loaded. It appears to be completely random. There must be some loading timing or thread issue

Seeing this in Expo 49 currently, if you implemented useFont per the documentation:

  const onLayoutRootView = useCallback(async () => {
    if (fontsLoaded) {
      await SplashScreen.hideAsync();
    }
  }, [fontsLoaded]);

  if (!fontsLoaded) {
    return null;
  } 

Your app will randomly hang on the splash screen on iOS. I haven’t confirmed on Android. It’s easy to reproduce this. Force quit 10-15 times and you will get the app to hang on the splashscreen.

I also added a setTimeout to force the splash to hide because this is a pretty bad issue to have out in the wild. It possible a fresh install will never get into the app, I’ve seen this a few times now.

@douglowder I got this issue straight off the bat with npx create-expo-app@latest -t tabs@50

For what it’s worth I don’t think this is the fonts hook that is failing, it’s a assets loading issue. When this issue shows up, the in-app images don’t load either.

This does seem to be correct or at least related. In the errors we are seeing reported, it is complaining that the font asset file doesn’t even exist.

File 'file:///var/mobile/Containers/Data/Application/[....]/Library/Application%20Support/.expo-internal/assets/node_modules/@expo-google-fonts/montserrat/Montserrat_400Regular.ttf' for font 'Montserrat_400Regular' doesn...

Given the version that is being logged, it looks like the issue is also causing the app to fallback to the bundle that was shipped with the binary build versus the latest OTA. This seems to be a pretty prevalent issue for us, so any additional findings would be welcome.

For what it’s worth I don’t think this is the fonts hook that is failing, it’s an assets loading issue. When this issue shows up, the in-app images don’t load either.

Tried all solutions suggested here, including loading from @expo-google-fonts - no luck on Expo 49. My CLI is throwing errors about this issue should remain open @douglowder.

Thank you thank you @carbonatedcoder ! We will investigate and determine why expo-insights is causing this issue.

Robert: I actually figured out a fix that worked for me. For some reason the splashScreen would never register the value of fontsLoaded changing, but I was able to fix the issue by using the deprecated element called AppLoading from expo-app-loading. All I did was do if (!fontsLoaded) { return <AppLoading/> } This correctly kept the screen loading until the fonts were loaded. After they were loaded it stopped showing the loading screen. Hope this helps you out, and if anybody figures out why it’s not working with SplashScreen please let me know

Oh my goodness, we had been tearing our hairs out for weeks trying to resolve this issue. Very hard to diagnose. Can’t believe it was Expo-Insights this whole time. Sorry, ol’ package, we cannot risk something like this again.

Thank you so much for figuring out this issue.

Thanks much! It would be useful to know the versions you are using of the following packages:

  • expo-updates 0.18.13
  • expo-asset 8.10.1 (dependency via expo)
  • expo-font 11.4.0 (dependency via expo)
  • expo-manifests 0.7.2 (dependency via expo-updates)

if you are seeing the message above, it means that you are not actually using expo-updates, and should remove it from your app.

@douglowder, thanks for the followup, but we do actually make use of expo-updates in the app and have a custom handler for OTA update checking/processing (checkForUpdateAsync, fetchUpdateAsync, and reloadAsync).

Additionally, we use reloadAsync in a few places throughout the app successfully to restart the app for different purposes. The only time it fails with this error is while being called during/after this assets issue is taking place. So, I’m not sure if it’s something to do with the app falling back to the built in bundle or what.