How to use `expo-splash-screen` with `expo-google-fonts`?

3.3k views Asked by At

The splash screen is using async operations to wait, while the fonts package is using a "custom hook" useFonts (I guess). How to make the splash screen wait for the google fonts to load?

2

There are 2 answers

3
Dmitro_ On BEST ANSWER

You can load fonts with loadAsync from expo-fonts, and manage splash screen with expo-splash-screen

import * as SplashScreen from 'expo-splash-screen';
import * as Font from 'expo-font';
import { Inter_900Black } from '@expo-google-fonts/inter';

export default function App() {
  const [appIsReady, setAppIsReady] = useState(false);

  useEffect(() => {
    (async () => {
      try {
        await SplashScreen.preventAutoHideAsync();
        await Font.loadAsync({ Inter_900Black });
      }
      catch {
        // handle error
      }
      finally {
        setAppIsReady(true);
      }
    })();
  }, []);

  const onLayout = useCallback(() => {
    if (appIsReady) {
      SplashScreen.hideAsync();
    }
  }, [appIsReady]);

  if (!appIsReady) {
    return null;
  }

  return (
      <View style={styles.container} onLayout={onLayout}>
        <Text style={{fontFamily: 'Inter_900Black'}}>
          Example text
        </Text>
      </View>
  );
}
0
edwDev On

This is compete!

import React, { useCallback, useEffect, useState } from 'react';
import * as SplashScreen from 'expo-splash-screen';
import * as Font from 'expo-font';
import { Montserrat_400Regular, Montserrat_500Medium, Montserrat_700Bold, 
Montserrat_900Black } from '@expo-google-fonts/montserrat';

export default function App() {
const [appIsReady, setAppIsReady] = useState(false);

useEffect(() => {
 async function prepare() {
  try {
    // Keep the splash screen visible while we fetch resources
    await SplashScreen.preventAutoHideAsync();

    // Pre-load fonts, make any API calls you need to do here
    await Font.loadAsync({ Montserrat_900Black });
    
    // Artificially delay for two seconds to simulate a slow loading
    // experience. Please remove this if you copy and paste the code!
    await new Promise(resolve => setTimeout(resolve, 2000));
  } catch (e) {
    console.warn(e);
  } finally {
    // Tell the application to render
    setAppIsReady(true);
  }
}

prepare();
}, []);

const onLayoutRootView = useCallback(async () => {
 if (appIsReady) {
  // This tells the splash screen to hide immediately! If we call this after
  // `setAppIsReady`, then we may see a blank screen while the app is
  // loading its initial state and rendering its first pixels. So instead,
  // we hide the splash screen once we know the root view has already
  // performed layout.
  await SplashScreen.hideAsync();
}
}, [appIsReady]);

if (!appIsReady) {
 return null;
}

return (
 <View
  style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}
  onLayout={onLayoutRootView}>
  <Text style={{ fontFamily: 'Montserrat_900Black', fontSize: 18 }}>SplashScreen 
  Demo! </Text>
</View>
);
}'