Loading font native-base error

Viewed 23326

I'm getting the error: You started loading 'Roboto_medium', but used it before it finished loading when using native base.

enter image description here

I've followed the instructions in the official page.

To create react native app I'm using create-react-native-app.

App.js

export default class App extends React.Component {

async componentWillMount() {
  await Expo.Font.loadAsync({
  'Roboto': require('native-base/Fonts/Roboto.ttf'),
  'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
  'Ionicons': require('@expo/vector-icons/fonts/Ionicons.ttf'),
 });
}

 render() {
   return (
    <Container>
      <StatusBar hidden={true} />

    <Button>
      <Text>
        Button
      </Text>
    </Button>

    <ListaItens />
    </Container>
  );
}
} 
6 Answers

you need to wait till the fonts get loaded. You can do something like this

import React from "react";
import { StatusBar } from "react-native";
import { Container, Button, text, ListItem, Text } from "native-base";
import Expo from "expo";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { loading: true };
  }

  async componentWillMount() {
    await Expo.Font.loadAsync({
      Roboto: require("native-base/Fonts/Roboto.ttf"),
      Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
      Ionicons: require("@expo/vector-icons/fonts/Ionicons.ttf"),
    });
    this.setState({ loading: false });
  }

  render() {
    if (this.state.loading) {
      return <Expo.AppLoading />;
    }
    return (
      <Container>
        <StatusBar hidden={true} />

        <Button>
          <Text>Button</Text>
        </Button>

        <ListItem />
      </Container>
    );
  }
}

This new code for expo SDK 35 which was modified from @akhil xavier 's answer

First install expo-font

expo install 'expo-font'

here is the App.js

import React from "react";
import * as Font from "expo-font";
import { ActivityIndicator } from "react-native";
import { Root } from "native-base";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { loading: true };
  }

  async componentWillMount() {
    await Font.loadAsync({
      Roboto: require("native-base/Fonts/Roboto.ttf"),
      Roboto_medium: require("native-base/Fonts/Roboto_medium.ttf"),
      Ionicons: require("@expo/vector-icons/build/vendor/react-native-vector-icons/Fonts/Ionicons.ttf"),
    });
    this.setState({ loading: false });
  }

  render() {
    if (this.state.loading) {
      return <ActivityIndicator />;
    }
    return (
      <Root>
       <RootPage /> // starter component (i.e. nav)
      </Root>
    );
  }
}

The solution that works for me is below. The error I had was that I imported Font as (Fonts) but while calling it failed to notice the 's'. Fixed it by making sure the import name is similar to what you call the loadAsync to. You need to have 'expo-font' installed in your project for it to work

import React from "react";
import * as Font from "expo-font";
import { AppLoading } from "expo";
import MealsNavigator from "./navigation/MealsNavigator";


const fetchFonts = () => {
  return Font.loadAsync({
    "open-sans": require("./assets/fonts/OpenSans-Regular.ttf"),
    "open-sans-bold": require("./assets/fonts/OpenSans-Bold.ttf")
  });
};

export default function App() {
  const [fontLoaded, setFontLoaded] = useState(false);
  if (!fontLoaded) {
    return (
      <AppLoading
        startAsync={fetchFonts}
        onFinish={() => setFontLoaded(true)}
        onError={err => console.log(err)}
      />
    );
  }
  return <MealsNavigator />;
}

This is the way which I use to load Fonts in my project. I feel this more abstracted as compared to all the other answers.

What you need to do is create a custom hook to Load fonts

You can do it something like this

Create a folder called hooks where your App.js is located. Then inside hooks folder create a file called useFonts.js

Inside useFonts.js write like this

import * as Font from 'expo-font';

export default useFonts = async () =>
  await Font.loadAsync({
    Roboto: require('native-base/Fonts/Roboto.ttf'),
    Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
    Ionicons: require('@expo/vector-icons/fonts/Ionicons.ttf'),
  });

Now in your App.js write like this

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

import useFonts from './hooks/useFonts';

export default function App() {
  const [IsReady, SetIsReady] = useState(false);

  // This function will start the fontLoading
  const LoadFonts = async () => {
    await useFonts();
  };

  // This is a check to ensure fonts get loaded
  if (!IsReady) {
    return (
      <AppLoading
        startAsync={LoadFonts}
        onFinish={() => SetIsReady(true)}
        onError={() => {}}
      />
    );
  }

  // If fonts are successfully loaded then show the rest of your App
  return (
    <Container>
      <StatusBar hidden={true} />

      <Button>
        <Text>Button</Text>
      </Button>

      <ListaItens />
    </Container>
  );
}

One reason why it has to load font is because you are using the Native Base Text component. If you import the React Native Text component instead you won't even have to load fonts and you won't see that error.

Related