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

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.