Importing fonts with SDK 32

#1

Hello,

As always, thanks for all the work with Expo. It is a great tool and has helped me a lot.

I recently upgraded to SDK 32 and I received an error report from Sentry for my app, saying:

Error: Font.loadAsync unexpected exception: Font not found

I believe it has something to do with the changes in your post on SDK 32:

Similarly, in the expo-font module we’ve deprecated the import { Font } from 'expo-font'; syntax in favor of individually named exports ( import * as Font from 'expo-font'; ). Upgrade @expo/vector-icons if you get a warning about this.

I currently use this in App.js:

import { AppLoading, Font } from 'expo';

Should I replace it with this?

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

And is it literally an asterisk I should put, or replace it with the font name(s)?

Also, your post says:

We’ve also removed deprecated support for passing an array into Font.loadAsync. This feature displayed a deprecation warning for several SDK versions so if you didn’t see it, this change shouldn’t affect you.

In my App.js I load an object (not an array) with my icons, so is that still OK?

export default class App extends React.Component {
  state = {
    fontLoaded: false
  };
  async UNSAFE_componentWillMount() {
    try {
      // Bugfix: We include 'Material Icons' as well so that icons show when viewed through Expo (when in development)
      // See here: https://github.com/react-native-training/react-native-elements/issues/1005#issuecomment-373689090
      // See here: https://javascriptrambling.blogspot.com/2018/03/expo-icon-fonts-with-react-native-and.html
      await Font.loadAsync({
        'Material Icons': require('@expo/vector-icons/fonts/MaterialIcons.ttf'),
        MaterialIcons,
        FontAwesome,
        Ionicons
      });
      this.setState({ fontLoaded: true });
    } catch (error) {
      // console.log('error loading icon fonts', error);
    }
  }
  render() {
    if (!this.state.fontLoaded) {
      return <AppLoading />;
    }
    return <Root store={store} persistor={persistor} />;
  }
}

Thanks in advance for any help you can provide.

#2

Ran into this yesterday. Yes, it’s an actual * and an object should work fine. Here’s what my component looks like (removed a bunch of the redux-y stuff).

import React, { Component } from 'react';
import { AppLoading } from 'expo';
import * as Font from 'expo-font';
import _ from 'lodash';

export class AuthLoading extends Component {
  constructor(props) {
    super(props);

    this.cacheResourcesAsync = this.cacheResourcesAsync.bind(this);
  }

  async cacheResourcesAsync() {
    await Font.loadAsync({
      'parisienne-regular': require('../assets/fonts/parisienne/Parisienne-Regular.ttf'),
      'poppins-regular': require('../assets/fonts/poppins/Poppins-Regular.ttf'),
      'poppins-medium': require('../assets/fonts/poppins/Poppins-Medium.ttf'),
      'poppins-bold': require('../assets/fonts/poppins/Poppins-Bold.ttf'),
      'poppins-light': require('../assets/fonts/poppins/Poppins-Light.ttf')
    });

    // After fonts loaded actions
  }

  render() {
    return (
      <AppLoading
        startAsync={this.cacheResourcesAsync}
        onFinish={() => console.log('finished')}
        onError={console.warn}
      />
    );
  }
}
#3

Thanks very much @mwood23 for the detailed reply. I’ve updated my app as suggested, and hopefully I won’t be seeing that error anymore in my logs (I personally never saw it in my testing so will need to rely on Sentry).

Thanks again.

closed #4

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.