How do I set custom fonts in React Native? - react-native

My code is as follows:
import { StatusBar } from 'expo-status-bar';
import Home from './screens/home';
import * as Font from 'expo-font';
import React, { useState } from 'react';
import { AppLoading } from 'expo-app-loading';
const getFonts = () => Font.loadAsync({
'montserrat-regular': require('./assets/fonts/Montserrat-Regular.ttf'),
'montserrat-medium': require('./assets/fonts/Montserrat-Medium.ttf'),
'wreath': require('./assets/fonts/insigne - Wreath Halftone Medium.otf'),
});
export default function App() {
const [fontsLoaded, setFontsLoaded] = useState(false);
if(fontsLoaded)
{
return (
<Home />
);
} else{
return(
<AppLoading
startAsync = {getFonts}
onFinish={() => setFontsLoaded(true)}
/>
)
}
}
and this is showing the following error:
Render Error
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of 'App'.
The fonts should work as I am learning but it's throwing an error while working propoerly if I remove the fonts

It might be because of your getFonts is not async function. Try making it async like below:
const getFonts = async () => await Font.loadAsync({
'montserrat-regular': require('./assets/fonts/Montserrat-Regular.ttf'),
'montserrat-medium': require('./assets/fonts/Montserrat-Medium.ttf'),
'wreath': require('./assets/fonts/insigne - Wreath Halftone Medium.otf'),
});

Related

React Native Expo fonts, They are loaded but I can't see the change in my application interface

I am new to using react native. I am using the code contributed in other topics similar to this one:
I use a hook:
import * as Font from "expo-font";
export default useFonts = async () =>
await Font.loadAsync({
Bebas: require('../assets/fonts/BebasNeue-Regular.ttf'),
Montserrat: require('../assets/fonts/Montserrat-Italic-VariableFont_wght.ttf'),
Inter: require('../assets/fonts/Inter-Black.otf')
});
And then in my app.js:
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);
const LoadFonts = async () => {
await useFonts();
};
if (!IsReady) {
return (
<AppLoading
startAsync={LoadFonts}
onFinish={() => SetIsReady(true)}
onError={() => {}}
/>
);
}
return <View styles={styles.container}>{/* Code Here */}</View>;
}
I then try to use them with the same name in my different screens, and I think they are loaded correctly, (no error), but I can't see the change when I restart my application.

React native : Problem Loading Fonts in a custom Hook

I am trying To make a custom hook that loads fonts using {useFonts} from expo, so that i wont have to repeat the code evrytime, and here is what I got so far.
import { useFonts } from "expo-font";
export default useAppFonts = () => {
const [loaded] = useFonts({
RobotoSlabBlack: require("../Fonts/RobotoSlab-Black.ttf"),
RobotoSlabBold: require("../Fonts/RobotoSlab-Bold.ttf"),
RobotoSlabExtraBold: require("../Fonts/RobotoSlab-ExtraBold.ttf"),
RobotoSlabExtraLight: require("../Fonts/RobotoSlab-ExtraLight.ttf"),
RobotoSlabThin: require("../Fonts/RobotoSlab-Thin.ttf"),
RobotoSlabRegular: require("../Fonts/RobotoSlab-Regular.ttf"),
});
return loaded;
};
the problem is that it works the first time I load the app but when I reload it stops working and the text reverts back to default fonts.
making a custom text component with the fonts already it came to mind, but it really bothers me that I can't do it like this.
and if its not possible I would like to know that, thank you for anyone with a response.
Use loadAsync instead of useFonts
To loadFonts which I do in all my project is create a folder called hooks where your App.js is located
Then, Install expo-app-loading & expo-font
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({
"Montserrat-Bold": require("../assets/fonts/Montserrat-Bold.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);
const LoadFonts = async () => {
await useFonts();
};
if (!IsReady) {
return (
<AppLoading
startAsync={LoadFonts}
onFinish={() => SetIsReady(true)}
onError={() => {}}
/>
);
}
return <View styles={styles.container}>{/* Your App Code Here */}</View>;
}

Expo fontello don't load

I'm trying to load a fontello icons in my project, but if I try to load in App.js, it send "false' and the app don't load:
import React, {useState} from "react";
import AppLoading from "expo-app-loading";
import { ThemeProvider } from "styled-components";
import theme from "./src/globalStyles/theme";
import Routes from "./src/routes";
import {
useFonts,
Roboto_400Regular,
Roboto_500Medium,
Roboto_700Bold,
} from "#expo-google-fonts/roboto";
import { Fontello } from "./assets/fonts/fontello.ttf";
export default function App() {
const [fontsLoaded] = useFonts({
Roboto_400Regular,
Roboto_500Medium,
Roboto_700Bold,
Fontello,
});
console.log(fontsLoaded)
if (!fontsLoaded) {
return <AppLoading />;
}
return (
<ThemeProvider theme={theme}>
<Routes />
</ThemeProvider>
);
}
And if I comment the line with Fontello, it load the app but I got the following error:
fontFamily "fontello" 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.
Install expo-font
expo install expo-font
Create a folder called hooks where you App.js is located.
Inside hooks folder create a file called useFonts.js paste this code
useFonts.js
import * as Font from 'expo-font';
import { Roboto_400Regular } from '#expo-google-fonts/roboto';
const useFonts = async () => {
await Font.loadAsync({
Roboto: Roboto_400Regular,
Fontello: require('../assets/fonts/fontello.ttf'),
// All Other Fonts
});
};
export default useFonts;
Then in your App.js paste this code
import React, { useState } from 'react';
import AppLoading from 'expo-app-loading';
import { ThemeProvider } from 'styled-components';
import theme from './src/globalStyles/theme';
import Routes from './src/routes';
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 (
<ThemeProvider theme={theme}>
<Routes />
</ThemeProvider>
);
}
Working Example Works on Android. Some bug in the web version.

Check the render method of `InstanceImage` while testing using testing-library/react-native

I am trying to test a functional component with Redux using testing-library/react-native.
//InstanceImage.component.js
export default InstanceImage = (props) => {
// <props init, code reduced >
const { deviceId, instanceId } = DeviceUtils.parseDeviceInstanceId(deviceInstanceId)
const deviceMap = useSelector(state => {
return CommonUtils.returnDefaultOnUndefined((state) => {
return state.deviceReducer.deviceMap
}, state, {})
})
const device = deviceMap[deviceId]
const instanceDetail = device.reported.instances[instanceId]
if (device.desired.instances[instanceId] !== undefined) {
return (
<View
height={height}
width={width}
>
<ActivityIndicator
testID={testID}
size={loadingIconSize}
color={fill}
/>
</View>
)
}
const CardImage = ImageUtils[instanceDetail.instanceImage] === undefined ? ImageUtils.custom : ImageUtils[instanceDetail.instanceImage]
return (
<CardImage
testID={testID}
height={height}
width={width}
fill={fill}
style={style}
/>
)
}
And the test file is
//InstanceImage.component.test.js
import React from 'react'
import { StyleSheet } from 'react-native';
import { color } from '../../../../src/utils/Color.utils';
import ConstantsUtils from '../../../../src/utils/Constants.utils';
import { default as Helper } from '../../../helpers/redux/device/UpdateDeviceInstanceIfLatestHelper';
import InstanceImage from '../../../../src/components/Switches/InstanceImage.component';
import { Provider } from 'react-redux';
import { render } from '#testing-library/react-native';
import configureMockStore from "redux-mock-store";
import TestConstants from '../../../../e2e/TestConstants';
const mockStore = configureMockStore();
const store = mockStore({
deviceReducer: {
deviceMap: Helper.getDeviceMap()
}
});
const currentState = ConstantsUtils.constant.OFF
const styles = StyleSheet.create({
// styles init
})
const props = {
//props init
}
describe('Render InstanceImage', () => {
it('InstanceImage renders correctly with values from props and Redux', () => {
const rendered = render(<Provider store={store}>
<InstanceImage {...props}/>
</Provider>)
const testComponent = rendered.getByTestId(TestConstants.icons.INSTANCE_IMAGE)
});
})
And when I run the test file it gives the following error
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `InstanceImage`.
The component runs correctly when the app is run and there aren't any crashes. Still, this error occurs while performing tests.I am new to creating test cases for react native app so not able to debug this issue.
Found the error, the CardImage returns a custom svg image which was causing the issue. I used the jest-svg-transformer and it solved the issue.
Reference: https://stackoverflow.com/a/63042067/4795837

Element type is invalid: expected a string (for built-in components) or class/function (for composite components) but got: undefined

Hi I am starting to use react native, but I have problem using nativebase with expo.
When using the code in the documentation this error appears:
Element type is invalid: expected a string (for built-in components) or class / function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of 'App'
[Here the error] (https://ibb.co/nQpBqYv)
import React from 'react';
import { AppLoading } from 'expo-app-loading';
import { Container, Text } from 'native-base';
import * as Font from 'expo-font';
import { Ionicons } from '#expo/vector-icons';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isReady: false,
};
}
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 });
}
render() {
if (!this.state.isReady) {
return <AppLoading />;
}
return (
<Container>
<Text>Open up App.js to start working on your app!</Text>
</Container>
);
}
}
The problem is not with the nativebase. You actually need to correct the following import statement,
import { AppLoading } from 'expo-app-loading';
to the following,
import AppLoading from 'expo-app-loading';