React Native Async Font Loading - react-native

I'm building a React native code project using react-native-cli, is there anyway to Async Load fonts without Expo? Would there be a problem simply importing { Font } from 'expo' in my cli native project?

If you want to use the external font (e.g. Google fonts, etc.) or any vector icons (e.g. ant icons), you have to load before app render, like this
import * as Font from "expo-font";
import { AppLoading } from "expo";
async componentDidMount() {
await Font.loadAsync(
"antoutline",
require("#ant-design/icons-react-native/fonts/antoutline.ttf")
);
await Font.loadAsync(
"antfill",
require("#ant-design/icons-react-native/fonts/antfill.ttf")
);
this.setState({ isReady: true });
}
render() {
const { theme, currentTheme, isReady } = this.state;
if (!isReady) {
return <AppLoading />;
}
const Loader = createAppContainer;
return (
<Provider theme={theme}>
<Loader />
</Provider>
);
}

Related

React Native Expo CLI Import .ttf Fonts

Trying to import .ttf for font in expo cli.
I also have splash screen. I wanna show the splash screen until the font loads.
Font: Josefin Sans.
"expo": "~45.0.0"
I took reference from following links but nothing works:
Using Custom Fonts: https://docs.expo.dev/guides/using-custom-fonts/
Splash Screen: https://docs.expo.dev/versions/latest/sdk/splash-screen/
Code (App.js)
import { useState, useEffect, useCallback } from "react";
import { Text } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { StatusBar } from "expo-status-bar";
import Header from "./components/Header.component";
import styles from "./styles/appStyle";
import * as Font from "expo-font";
import * as SplashScreen from "expo-splash-screen";
const App = () => {
const [appIsReady, setAppIsReady] = useState(false);
useEffect(() => {
async function prepare() {
try {
// Pre-load fonts
await Font.loadAsync({
"JosefinSans-Regular": require("./assets/fonts/JosefinSans-Regular.ttf"),
});
// Artificially delay for two seconds to simulate a slow loading
// experience. Please remove this if you copy and paste the code!
await new Promise((resolve) => setTimeout(resolve, 2000));
} catch (e) {
} finally {
// Tell the application to render
setAppIsReady(true);
}
}
prepare();
}, []);
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
// This tells the splash screen to hide immediately! If we call this after
// `setAppIsReady`, then we may see a blank screen while the app is
// loading its initial state and rendering its first pixels. So instead,
// we hide the splash screen once we know the root view has already
// performed layout.
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return (
<>
<SafeAreaView style={styles.container} onLayout={onLayoutRootView}>
<Header />
<Text>Hello World!</Text>
<StatusBar style="light" backgroundColor="#05060B" />
</SafeAreaView>
</>
);
};
export default App;
Error
Android Bundling failed 12ms
Unable to resolve module ./assets/fonts/JosefinSans-Regular.ttf from C:\Users\user\Desktop\app\App.js:
None of these files exist:
* JosefinSans-Regular.ttf
* assets\fonts\JosefinSans-Regular.ttf\index(.native|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx|.android.js|.native.js|.js|.android.jsx|.native.jsx|.jsx|.android.json|.native.json|.json)
18 | // Pre-load fonts
19 | await Font.loadAsync({
> 20 | "JosefinSans-Regular": require("./assets/fonts/JosefinSans-Regular.ttf"),
| ^
21 | });
22 | // Artificially delay for two seconds to simulate a slow loading
23 | // experience. Please remove this if you copy and paste the code!
File Structure:
Snap.png
Answer
expo install #expo-google-fonts/josefin-sans expo-font
And the code looks like this.
import { useState, useEffect, useCallback } from "react";
import { Text } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { StatusBar } from "expo-status-bar";
import Header from "./components/Header.component";
import styles from "./styles/appStyle";
import * as Font from "expo-font";
import * as SplashScreen from "expo-splash-screen";
import {
useFonts,
JosefinSans_100Thin,
JosefinSans_200ExtraLight,
JosefinSans_300Light,
JosefinSans_400Regular,
JosefinSans_500Medium,
JosefinSans_600SemiBold,
JosefinSans_700Bold,
JosefinSans_100Thin_Italic,
JosefinSans_200ExtraLight_Italic,
JosefinSans_300Light_Italic,
JosefinSans_400Regular_Italic,
JosefinSans_500Medium_Italic,
JosefinSans_600SemiBold_Italic,
JosefinSans_700Bold_Italic,
} from "#expo-google-fonts/josefin-sans";
const App = () => {
const [appIsReady, setAppIsReady] = useState(false);
let [fontsLoaded] = useFonts({
JosefinSans_100Thin,
JosefinSans_200ExtraLight,
JosefinSans_300Light,
JosefinSans_400Regular,
JosefinSans_500Medium,
JosefinSans_600SemiBold,
JosefinSans_700Bold,
JosefinSans_100Thin_Italic,
JosefinSans_200ExtraLight_Italic,
JosefinSans_300Light_Italic,
JosefinSans_400Regular_Italic,
JosefinSans_500Medium_Italic,
JosefinSans_600SemiBold_Italic,
JosefinSans_700Bold_Italic,
});
const prepare = async () => {
try {
// Pre-load fonts
await Font.loadAsync(fontsLoaded)
.then(() => {
setAppIsReady(true);
})
.catch((err) => {});
// Artificially delay for two seconds to simulate a slow loading
// experience. Please remove this if you copy and paste the code!
// await new Promise((resolve) => setTimeout(resolve, 2000));
} catch (e) {}
};
useEffect(() => {
prepare();
}, []);
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
// This tells the splash screen to hide immediately! If we call this after
// `setAppIsReady`, then we may see a blank screen while the app is
// loading its initial state and rendering its first pixels. So instead,
// we hide the splash screen once we know the root view has already
// performed layout.
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return (
<>
<SafeAreaView style={styles.container} onLayout={onLayoutRootView}>
<Header />
<Text>Hello World!</Text>
<StatusBar style="light" backgroundColor="#05060B" />
</SafeAreaView>
</>
);
};
export default App;

How can I add custom font in react native without generating any error in my previous written code?

I'm using expo-cli, can somebody help me in using custom fonts for Expo Managed React Native projects.
Image Link
Install expo-font
expo install expo-font
Then install expo-app-loading
expo install expo-app-loading
Create a folder called hooks where your App.js is located.
Inside hooks folder create a file called useFonts.js paste this code
useFonts.js
import * as Font from 'expo-font';
const useFonts = async () => {
await Font.loadAsync({
Fontello: require('../assets/fonts/fontello.ttf'),
// Place your custom fonts here and make sure that their location is set properly
});
};
export default useFonts;
Then in your App.js paste this code
import React, { useState } from 'react';
import AppLoading from 'expo-app-loading';
import useFonts from './hooks/useFonts';
export default function App() {
const [IsReady, setIsReady] = useState(false);
const LoadFonts = async () => {
await useFonts();
};
if (!IsReady) {
return (
<AppLoading
startAsync={LoadFonts}
onFinish={() => setIsReady(true)}
onError={(error) => console.log(error)}
/>
);
}
return (
<View>
// Your App Content here
</View
);
}
Working Example

Not able to install Native Base in my react prject

Does using expo react native doesn't allow to install native base ?
It is documented in nativebase website. You will have to install expo-font and make some adjustments in App.js. The official documentation link is https://docs.nativebase.io/docs/GetStarted.html#Setup_with_Expo
No, expo doesn't stop you from using any frontend package, because there is a specific way to install native base after installing native-base. Put the following code in your main react-native file
import React, { Component } from 'react';
import { Root } from 'native-base';
import Main from "project directory";
import * as Font from 'expo-font';
import { ActivityIndicator } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = { loading: true };
}
async componentDidMount() {
await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
});
this.setState({ loading: false });
}
render() {
if (this.state.loading) {
return (
<Root>
<ActivityIndicator />
</Root>
);
} else {
return (
<Root>
<Main/>//Your main Javascript project file.
</Root>
);
}
}
}

console.error: "fontFamily "Roboto_medium" is not a system font and has not been loaded through Font.loadAsync

When using import Native Base (as it comes) I have encountered trouble because of a Font error shown in screen. If you click dismiss it will disappear but the user can't be seeing that every time a Text gets loaded. ¿Is there a correct way to solve the font problem?
This official documentation says to do this:
// At the top of your file
import { Font } from 'expo';
import { Ionicons } from '#expo/vector-icons';
// Later on in your component
async componentDidMount() {
await Font.loadAsync({
'Roboto': require('native-base/Fonts/Roboto.ttf'),
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
...Ionicons.font,
});
}
but it didn't work. This is my code:
import React, { Component } from 'react';
import { View, } from "react-native";
import { Button, Text } from 'native-base';
export default class MyComponent extends Component {
render() {
return (
<View>
<Button>
<Text>Click me!</Text>
</Button>
</View>
)
}
}
I expect the code to run smoothly but every time it loads the same error:
console.error: "fontFamily "Roboto_medium" is not a system font and has not been loaded through Font.loadAsync.
- If you intended to use a system font, make sure you typed the name correctly and that it is supported by your device operating system.
- If this is a custom font, be sure to load it with Font.loadAsync."
__expoConsoleLog
AppEntry.bundle?platform=android&dev=true&minify=false&hot=false:95014:31
...................
...................
...................
Native Base uses Roboto_Medium as a font for Title and some objects. Roboto_Medium is not a system font.
You can do either two things
Install and Load Roboto_Medium font in your codebase.
Edit existing Native Base core files
1) Install and Load Roboto_Medium font in your codebase
After installing Native Base, run these in terminal expo install expo-font.
After that Open your App.js file, add this two lines,
import * as Font from 'expo-font';
import { Ionicons } from '#expo/vector-icons';
After that include function componentDidMount()
async componentDidMount() {
await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
...Ionicons.font,
});
this.setState({ isReady: true });
}
You must call componentDidMount() function. If you are using Class Component, then this can be called using constuctor method
constructor(){
componentDidMount();
}
But, if you are using Functional Method, then you have manually call the componentDidMount() function.
2) Edit existing Native Base core files (Alternative)
You have to edit core Native Base files.
Location of File:
commonColor.js
node_modules\native-base\dist\src\theme\variables \ commonColor.js
material.js
node_modules\native-base\dist\src\theme\variables \ material.js
platform.js
node_modules\native-base\dist\src\theme\variables \ platform.js
In this files, find "Roboto_Medium" and replace it with "Roboto" or any other system default fonts.
But, as we have hardcoded the node_modules, with each update of Native Base, you have to again hard code the values again.
If anyone still has this problem and is using functional components, i solved it like this:
import * as Font from 'expo-font';
useEffect(() => {
(async () => await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
}))();
}, [])
For newer Functional Components solved it like this
import { View } from 'react-native';
import { NativeBaseProvider, Text } from 'native-base';
const MyComponent = () => {
return (
<NativeBaseProvider>
<View>
<Text>Example Text</Text>
</View>
</NativeBaseProvider>
)
}
export default MyComponent;
For older Functional Components solved it like this
import { View } from 'react-native';
import { Text } from 'native-base';
import * as Font from 'expo-font';
const MyComponent = () => {
useEffect(() => {
(async () => await Font.loadAsync({
Roboto: require('native-base/Fonts/Roboto.ttf'),
Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
}))();
}, [])
return (
<View>
<Text>Example Text</Text>
</View>
)
}
export default MyComponent;
For Class Components solved it like this
import React, { Component } from 'react';
import { View, } from "react-native";
import { Button, Text } from 'native-base';
import { Font } from 'expo';
import { Ionicons } from '#expo/vector-icons';
export default class MyComponent extends Component {
state = {
loading: true
}
async componentDidMount() {
await Font.loadAsync({
'Roboto': require('native-base/Fonts/Roboto.ttf'),
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
...Ionicons.font,
})
this.setState({ loading: false })
}
render() {
if (this.state.loading) {
return (
<View></View>
);
}
return (
<View>
<Button>
<Text>Click me!</Text>
</Button>
</View>
)
}
}

Promise rejection when I try to load fonts in expo

I get a problem with Expo and react-native. When I try to loadAsync font from assets folder I get this error:
[Unhandled Promise rejection: Error: Font not found /data/data/host.exp.exponent/cache/ExperienceData/.../ExponentAsset-5868d2d7f28da04ee373451e87d682f8.ttf]
My code in App.js
import React, { Component } from "react";
import { configureStore } from "./store.js";
import { Provider } from "react-redux";
import { AppLoading, Font } from 'expo';
import MainWrapper from './components/mainWrapper'
const store = configureStore();
export default class App extends Component {
state = {
appReady: false
}
loadAssets = async () => {
await Font.loadAsync({
'Arial': require('./assets/fonts/Arial.ttf')
});
this.setState({appReady: true});
}
componentDidMount() {
this.loadAssets()
}
render() {
return (
<Provider store={store}>
{this.state.appReady ?
<MainWrapper />
:
<AppLoading />
}
</Provider>
);
}
}
and I use
"expo": {
"sdkVersion": "21.0.0"
}
Most of my App.js I took from Expo example with some changes. Do you have any ideas how can I resolve this error?
It was broken .ttf file. I downloaded correct file of font from another source and my problem has been resolved. But what about FontAwesome I will explore this.