Using Expo Custom Fonts with react-navigation


#1

I’m using CRNA together with react-navigation. My App has a bottom TabNavigator with 5 Tabs, each of which have a Font Icon loaded from a icomoon.ttf file using the steps from the Expo Custom Fonts tutorial. However, I’m getting a warning in the Terminal about Expo.Font not being available. I think the reason is that App.js imports the Routes component, which imports the Screen components, which imports the FontIcon component. The FontIcon import triggers the call to createIconSetFromIcomoon() call, which fires before the fonts can be loaded. Is there any way to avoid this?:

App.js

...
import Routes from './routes'
...

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

  async componentWillMount() {
    try {
      await FontLoader.load();
      this.setState({ fontLoaded: true });
    } catch (err) {
      // console.log(err);
    }
  }

  render() {
    return (
      this.state.fontLoaded
        ? <Routes />
        : <Text>Loading Fonts...</Text>
    );
  }
}

Routes.js

...
const MainScreenNavigator = TabNavigator({
  MainScreen: { screen: MainScreen },
},
...

MainScreen.js

const MainScreen = () => {
  static navigationOptions = {
    title: 'Home',
    tabBarIcon: ({ tintColor }) => (
      <FontIcon
        name="icon_dashboard"
        size={24}
        color={tintColor}
      />
    ),
  }
}

FontIcon.js

import React from 'react';
import PropTypes from 'prop-types';
import { createIconSetFromIcoMoon } from '@expo/vector-icons';

import icoMoonConfig from '../../../../assets/fonts/icomoon-config.json';

const Icon = createIconSetFromIcoMoon(icoMoonConfig, 'icons');

const FontIcon = (props) => {
  const { name, size, color } = props;

  return (
    <Icon
      name={name}
      size={size}
      color={color}
    />
  );
};

#2

For anyone still looking for this solution, I was able to do this by rewriting the FontIcon component like this.

import React from 'react';
import { Font } from 'expo';
import { View } from 'react-native';

import { createIconSetFromIcoMoon } from '@expo/vector-icons';
import icoMoonConfig from '../assets/fonts/icomoon-config.json';
const Icon = createIconSetFromIcoMoon(icoMoonConfig, 'Icomoon');

export default class FontIcon extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fontLoaded: false
    }
  }

  async componentDidMount() {
    await Font.loadAsync({
      'Icomoon': require('../assets/fonts/icomoon.ttf')
    });

    this.setState({fontLoaded: true});


  }

  render() {
    return (
      <View>
      {
        this.state.fontLoaded && (
          <Icon
            name={this.props.name}
            size={this.props.size}
            color={this.props.color}
          />
        )
      }
      </View>
    );
  }
}