Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using custom Font in react native with expo, loading font every time

I am using Expo and the create-react-native app. I enjoy the live/hot reloading feature on my phone, but I'm wondering about custom fonts.

https://docs.expo.io/versions/v17.0.0/guides/using-custom-fonts.html#loading-the-font-in-your-app

The API for Expo only has directions to load them asynchronously. Do I have to do this on every component I want a custom font on? This seems like it would cause some unnecessary calls when I've already loaded it once.

Is there a way to set the font as global or pass it via props once loaded? It seems like they suggest this approach via their last line in that link:

Note: Typically you will want to load your apps primary fonts before the app is displayed to avoid text flashing in after the font loads. The recommended approach is to move the Font.loadAsync call to your top-level component.

...But they give no explanation on HOW to do that, if that's what they are implying.

So my questions are:

1) Does loading the custom font in multiple times (on each component), cause performance issues? (or maybe it's pulled from cache after the first?)

2) After loading it can you pass the font down via properties or set it as a global?

and finally

3) Is this an Expo only issue? Or a create-react-native app only issue? Or just a livereload/hotloading issue?

Also note, I'm working on Windows/Android

like image 727
Organiccat Avatar asked Jun 01 '17 14:06

Organiccat


3 Answers

1) You should only load the font once. As you point out, Expo recommends putting the Font.loadAsync method in the componentDidMount() method of your top-level component.

The performance issue you're referring to is probably the magic that's happening behind the asynchronous call—but again, this should only happen once.

2) From that point forward, you can use the font in any child component using the "fontFamily" property on <Text>. As their example (which I modified slightly) shows:

First load the font in your top-level component.

export default class App extends React.Component {
  componentDidMount() {
    Font.loadAsync({
      'open-sans-bold': require('./assets/fonts/OpenSans-Bold.ttf'),
    });
  }

  render() {
    return (
       <HelloWorld />
    )
  }
}

Then use it in any component in the app. (Prior to the font loading, you will see the system font - San Francisco on iOS, Roboto on Android. This is why Expo recommends setting a loading state... to avoid awkward flashing between the system font and your newly loaded custom font.)

export default class HelloWorld extends React.Component {
  render() {
    <Text style={{ fontFamily: 'open-sans-bold', fontSize: 56 }}>
      Hello, world!
    </Text>
  }
}

3) This is an Expo-related "issue" (or solution... depending on how you look at it). For instance, on iOS, adding a custom font involves several steps (adding the font file to your native project, making sure the font shows in your Bundle Resources, adding the font to Info.plist...). Not sure what the process is for Android, but it's something different and probably annoying, too.

Expo has abstracted that away with their Font module, which allows you to do one thing - and get the same result across platforms. Which is pretty cool, in my book.

like image 167
bayyar Avatar answered Sep 24 '22 14:09

bayyar


To use a font(expo) efficiently you can load the font in the root most Component and when loaded you can update the status fontLoaded:true in the global state [Redux].

It is well explained by me on medium Refer This

Hope this helps.

like image 21
kida007 Avatar answered Sep 22 '22 14:09

kida007


I know the thread is old but this may helps others too. The direct use Font.asyncLoad() cause the system font error.

fontFamily "roboto-medium" is not a system font and has not been loaded through Font.loadAsync

export default class App extends React.Component {

    state = {
        assetsLoaded: false,
    };

    async componentDidMount() {
        await Font.loadAsync({
            'roboto-medium': require('./assets/fonts/Roboto-Medium.ttf')
        });

        this.setState({ assetsLoaded: true });
    }

    render() {

        const {assetsLoaded} = this.state;

        if( assetsLoaded ) {
            return (
                <View style={styles.container}>
                    <Text style={styles.heading}>Custom Roboto Font</Text>
                    <Text style={{fontSize: 40}}>Default Font</Text>
                </View>
            );
        }
        else {
            return (
                <View style={styles.container}>
                    <ActivityIndicator />
                    <StatusBar barStyle="default" />
                </View>
            );
        }
    }
}

If you like to know more in detail then please follow the link.

https://webomnizz.com/add-custom-font-to-react-native-using-expo/

like image 26
jogesh_pi Avatar answered Sep 23 '22 14:09

jogesh_pi