Can't seem to load custom fonts with Expo's Font.loadAsync

Viewed 13598

I'm using React Native with Expo, and it is all going well except for this one issue with custom fonts. I have my font Lobster-Regular.ttfin ./assets/fonts, and I have been trying to load it as seen in the official docs:

componentDidMount() {

    Font.loadAsync({

      'Lobster': require('./assets/fonts/Lobster-Regular.ttf'),
    });

  }

I then style my header as such:

  headerText: {
    color: 'white',
    fontSize: 30,
    fontFamily: 'Lobster'
  }, 

All I get is

fontFamily 'Lobster' is not a system font and has not been loaded through Font.loadAsync.

  • If you intended to use a system font, make sure you typed the name correctly and that it is supported by your device operating system.

  • If this is a custom font, be sure to load it with Font.loadAsync.

Am I missing something?

6 Answers

Yes. You are missing that the call is Font.loadAsync(). This means that it loads asynchronously. As in: It takes a while. You can't render the UI until the font has loaded. You need to do something along these lines:

import { AppLoading, Font } from 'expo'

state = {
    fontsLoaded: false,
    ...
}

componentWillMount() {
    Font.loadAsync( {
            'Lobster': require('./assets/fonts/Lobster-Regular.ttf')
        }
    ).then( () => this.setState( { fontsLoaded: true } ) )
}

render() {
    if( !this.state.fontsLoaded ) {
        return <AppLoading/>
    }

    return (
        ...
    )
}

Font.loadAsync is old and proved to have unpredictable problems. now expo have rolled out new solutions here

so the correct code is now:

import {useFonts} from 'expo-font';
import AppLoading from "expo-app-loading";

let [fontsLoaded] = useFonts({
      'Lobster': require('./assets/fonts/Lobster-Regular.ttf'),
    });
    if (!fontsLoaded) {
        return <AppLoading/>;
    }
...

install expo-font package from expo CLI because sometime expo-font version is not compatible with your expo version so,

step 1:

expo install expo-font

step 2:

class App extends React.Component {
  state = {
    fontLoaded: false,
  };

  componentDidMount() {
    this.loadAssetsAsync();
  }

  async loadAssetsAsync() {
    await Font.loadAsync({
      // Load a font `Montserrat` from a static resource
      MuseoSans500: require("./assets/fonts/museosans_500-webfont.ttf"),
      MuseoSans700: require("./assets/fonts/museosans_700-webfont.ttf"),
    });
    this.setState({ fontLoaded: true });
  }

  render() {
    if (!this.state.fontLoaded) {
      return null; // render some progress indicator
    }
    return <AnyComponent />;
  }
}


** react-native font in stateless function **

**step:1 import font from expo **

import * as Font from 'expo-font';
import { AppLoading } from 'expo';

*step2: require font from files *

// fetchFonts from local files type ttf 
const fetchFonts = () => {
  return Font.loadAsync({
  'PacificoRegular': require('../assets/Pacifico/Pacifico-Regular.ttf'),
  });
  };
*****step3:use state  *****
// state font fetch control 
const [fontloaded,setfontloaded]=useState(false);

**step4: use app loaded **

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

**step5:style font **

txt:{
padding:5,
fontSize:18,
fontFamily: 'PacificoRegular',
 }
useEffect(()=>{
    async function loadFonts(){
      await Font.loadAsync({
        'Montserrat': require("./assets/fonts/Montserrat/Montserrat-Regular.ttf"),
        'Montserrat-SemiBold': require('./assets/fonts/Montserrat/Montserrat-SemiBold.ttf'),
        'Montserrat-Bold': require('./assets/fonts/Montserrat/Montserrat-Bold.ttf'),
        'Fascinate': require('./assets/fonts/Fascinate/Fascinate-Regular.ttf')
      }).then(res=>{
        console.log("FONTS LOADED!");
        setLoaded(true)
      }).catch(Err=>{
        setLoaded(true);
        console.log(Err);
      }); 
    }

    loadFonts();
  },[])

Load using this useEffect in your App.js file, once loaded the fonts can be used anywhere in your expo or react-native project

const Heading = (color) => {
    return({fontSize:45*fontScale, fontFamily: "Montserrat-SemiBold", color, marginTop: -10, marginLeft: InitialMargin, letterSpacing: 4})
}

Make sure you are not using the style fontWeight, as it will override the fontStyle and will not apply the fontFamily to your Text.

Because 'startAsync' is depreacted from the component AppLoading,
we can use coustom fonts as bellow,
This code works fine.
I think <Apploading> causes no further instructions to be
performed until the font is loaded       
  
===============================================


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

export default function App() {
const [fontLoading,setFontLoading]=useState(false);
   
  Font.loadAsync( {
    yekan:require("./myapp/fonts/byekan.ttf"),
    ih:require("./myapp/fonts/ih.ttf")
      }
  ).then( () => setFontLoading('true') )
  
  
      if (!fontLoading){
       return(
         <AppLoading/>);
      
        } else{
          return(
         do someting.....
         ............
          ) 
}    
Related