React Native Expo.Font.loadAsync doesn't load Material Icons - react-native

I have a React Native, React hybrid app. For React Native i am using react-native-elements.
My app is run using Expo and was built out with the react-native init. I am getting the Material Icons (missing) RSD;
Through much searching, i have found the #expo/vector-icons but it doesn't seem to work. My App.js looks like this;
import React from 'react'
import { Font, AppLoading } from 'expo'
import { MaterialIcons } from '#expo/vector-icons'
import HybridApp from './src/App'
export default class NativeApp extends React.Component {
constructor() {
super()
this.state = {
fontsAreLoaded: false
}
}
async componentWillMount() {
await Font.loadAsync(MaterialIcons.font)
this.setState({ fontsAreLoaded: true })
}
render() {
const { fontsAreLoaded } = this.state
return !fontsAreLoaded ? <AppLoading /> : <HybridApp />
}
}
As you can see, i am waiting for the font to load... all to no avail.

After hours wracking my brain on this, the answer was there in front of me the whole time.
Presumably, React Native Elements refers to Material icons as Material Icons, not MaterialIcons.
This means that the default import from #expo/vector-icons does not work as their reference to Material icons is different.
The solution is to manually select Material icons from expo, replacing this line;
await Font.loadAsync(MaterialIcons.font)
with
await Font.loadAsync({
'Material Icons': require('#expo/vector-icons/fonts/MaterialIcons.ttf')
})
I hope this saves someone some time in the future.

The icons are actually fonts and must first be loaded. It seems they are autoloaded sometimes and others times are not.
So to ensure they are loaded, do this:
import FontAwesome from './node_modules/#expo/vector-icons/fonts/FontAwesome.ttf';
import MaterialIcons from './node_modules/#expo/vector-icons/fonts/MaterialIcons.ttf';
...
async componentWillMount() {
try {
await Font.loadAsync({
FontAwesome,
MaterialIcons
});
this.setState({ fontLoaded: true });
} catch (error) {
console.log('error loading icon fonts', error);
}
}
...
render() {
if (!this.state.fontLoaded) {
return <AppLoading />;
}
Then when you reference the type, it must be the same type that the component you are using is expecting.
For example, react native elements expects these types: material-community, font-awesome, octicon, ionicon, foundation, evilicon, simple-line-icon, zocial, or entypo
See complete answer here:
http://javascriptrambling.blogspot.com/2018/03/expo-icon-fonts-with-react-native-and.html

This question is old, but what worked for me and quite straightforward is
import { Ionicons } from "#expo/vector-icons";
await Font.loadAsync({...Ionicons.font, ...other imports })

Check if you have any dependency warnings when you run the app. I had an expo-font version warning, when I fixed it this error went away.
Some dependencies are incompatible with the installed expo package version:
- expo-font - expected version range: ~8.4.0 - actual version installed: ^9.1.0

Related

Using react native module (with native code) in expo project

I am working in an existing expo project (expo version 42.0.1 ) and I am unable to get this package working. It says in the package readme that it doesn't work with Expo, because it uses native code. But the readme is from a year ago and I thought Expo sdk42 allows you to use native modules now when you build your own custom client?
Does anyone know what I need to do to get this package working?
https://github.com/KjellConnelly/react-native-shared-group-preferences
Here's what i tried so far...
I added to my project with yarn add react-native-shared-group-preferences
And in App.js :
import 'expo-dev-client';
import React from 'react';
import { styles } from './src/components/CommonStyles';
import { useState } from 'react';
import { View, TextInput, Text } from 'react-native';
import SharedGroupPreferences from 'react-native-shared-group-preferences';
export default function App() {
const [inputText, setInputText] = useState('');
const widgetData = {
displayText: inputText,
};
const appGroupIdentifier = 'group.com.myproject.newwidget';
const handleSubmit = async () => {
try {
console.log('handleSubmit' + widgetData + appGroupIdentifier);
await SharedGroupPreferences.setItem(
'savedData', // this is a key to pull from later in Swift
widgetData,
appGroupIdentifier
);
} catch (error) {
console.log({ error });
}
};
return (
...
)
when I run the project with expo start and i to open iphone simulator,
I get this error: null is not an object (evaluating 'RNReactNativeSharedGroupPreferences.setItem')"
What am I doing wrong? Any help very much appreciated. Thanks

expo-location (React-Native) : Location.getCurrentPositionAsync() never returns anything

I'm developing a cross platform mobile App.
I'm testing my code on a Android Studio emulator (google pixel 5, api level 30) and i'm using expo version : ~43.0.2 and expo-location version : ~13.0.4
I've already asked for the location permission, and it works. But when I call the following code i log "there" but never "here":
console.log("there")
const userLocation = await Location.getCurrentPositionAsync()
console.log("here")
Indeed, the function Location.getCurrentPositionAsync() seems locked
A similar issue has been know in the past according to these links:
React Native Expo-Location returns Location service unavailable during initial useEffect
https://forums.expo.dev/t/getcurrentpositionasync-doesnt-return-any-value-infinity-loading/23643
But it's also the code in the Expo doc :
https://snack.expo.dev/#charliecruzan/expo-map-and-location-example
. Bellow the entire app class :
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import {Text, TextInput, Pressable, View, Alert} from 'react-native';
import * as Location from "expo-location"
export default class App extends React.Component{
state = {
errorMessage: "",
location: {}
}
getAddress(){
return this.state.address
}
_getLocation = async ()=>{
const {status} = await Location.requestForegroundPermissionsAsync();
if (status !== "granted"){
console.log("PERMISSION LACK!")
this.setState({
errorMessage:"PERMISSION NOT GRANTED"
});
}
console.log("there")
const userLocation = await Location.getCurrentPositionAsync();
console.log("here")
console.log(JSON.stringify(userLocation))
this.setState({
location: userLocation
})
}
render(){
this._getLocation()
return (
<View>
<Text>Salut</Text>
</View>
);
}
}
What did i missed?
Add accuracy and maximumAge in parameters with Location.Accuracy.Highest and 10000 respectively as shown below:
JavaScript:
const userLocation = await Location.getCurrentPositionAsync({accuracy: Location.Accuracy.Highest, maximumAge: 10000});
The solution came from How to use getCurrentPositionAsync
function in expo-location | Tabnine.
As explained in this reddit post, the location service only works in emulators if you are logged into a google account.

java.lang.String - facebook ad

I am using facebook ads. I wanted to put native ad to my react native expo app, but i got error. When i put simple banner all is ok. It gives me this error:
Uncaught Error: java.lang.String cannot be cast to java.lang.Double
I tried to import like this:
import * as FacebookAds from 'expo-ads-facebook';
but it gave me this error:
Unable to resolve "#unimodules/core" from "node_modules/expo-ads-facebook/build/withNativeAd.js"
What am i doing wrong?
// pageScreen.js
import React from 'react';
import { FacebookAds } from 'expo'
import AdScreenFacebook from './AdScreenFacebook'
class AdScreen extends React.Component {
render () {
return (
<AdScreenFacebook adsManager={adsManager} adChoicePosition="topLeft" expandable={false} />
);
}
}
// AdScreenFacebook.js
import React from 'react';
import { FacebookAds } from 'expo'
const { AdIconView, AdMediaView } = FacebookAds;
const adsManager = new FacebookAds.NativeAdsManager("2272791379702600_2272795453035526", "1");
class AdScreenFacebook extends React.Component {
render () {
return (
<View>
<AdMediaView />
<AdTriggerView>
<Text>{this.props.nativeAd.bodyText}</Text>
</AdTriggerView>
</View>
);
}
}
export default FacebookAds.withNativeAd(AdScreenFacebook);
export default createStackNavigator(
{
Main: {
screen: AdScreen,
},
AdScreenFacebook: {
screen: AdScreenFacebook,
}
},
{
initialRouteName: 'Main',
}
);
Remove the quotation marks from the number 1 in the NativeAdsManager function. You are currently passing that function the number 1 as a string instead of as a number.
// AdScreenFacebook.js
const adsManager = new FacebookAds.NativeAdsManager("2272791379702600_2272795453035526", 1);
With SDK 33, we’re deprecating imports of most modules from the expo package. This means that in a future release, you won’t be able to write, for example, import { FacebookAds } from 'expo';. Rather, you’ll need to install the individual packages for each module you use and import from them instead.
You can use the new expo install command to install modules; this command is a wrapper around npm install/yarn add that automatically installs a module version compatible with your SDK version. For example, for the FacebookAds module, you would run expo install expo-ads-facebook and then use import * as FacebookAds from 'expo-ads-facebook';. This change paves the way for tree-shaking and smaller JavaScript bundles. It also makes moving between the managed and bare workflows simpler.
If you want to use a Expo module such as a question, install it and set it up.
For managed apps, you'll need to run expo install expo-ads-facebook. To use it in a bare React Native app, follow its installation instructions.
Usage
import * as FacebookAds from 'expo-ads-facebook';
const { AdTriggerView, AdMediaView } = FacebookAds;
class AdComponent extends React.Component {
render() {
return (
<View>
<AdMediaView />
<AdTriggerView>
<Text>{this.props.nativeAd.bodyText}</Text>
</AdTriggerView>
</View>
);
}
}
export default FacebookAds.withNativeAd(AdComponent);

How to Implement UPI Payment in my React-Native-App with Expo?

I want to add UPI payment in my App and currently using expo tool to create the app but now I got stuck as there is unable to find any direct implementation by using js only and require me to eject from expo. If there is any way by which I can implement the UPI without exiting from expo as it expo makes things really easy.
I have tried to implement the simple code provided in the docs for react-native-upi-payment but it is not moving ahead and require me to move through android manifest which is not inside the expo project.
import React from 'react'
import RNUpiPayment from 'react-native-upi-payment'
import { View, StyleSheet, Container } from 'react-native'
import { Input, Button } from 'react-native-elements'
import { Constants } from 'expo'
export default class PaymentScreen extends React.Component {
static navigationOptions = {
header: null
}
goToBhimUPI = () => {
RNUpiPayment.initializePayment({
vpa: 'someupi#ybl', // or can be john#ybl or mobileNo#upi
payeeName: 'Name',
amount: '1',
transactionRef: 'some-random-id'
}, this.successCallback, this.failureCallback);
}
failureCallback = (data) =>{
console.log(data)
}
successCallback = (data) => {
console.log(data)
}
render() {
return(
<Button
containerStyle = {styles.button}
type = 'clear'
title = 'Bhim UPI'
onPress = {this.goToBhimUPI}
/>
)
}
}
I expect this module to take me to the UPI payment gateway and return to the place from where it is called. Currently this is giving me error:(undefined is not an object(evaluating 'UpiModule.intializePayment'))
you can do this using react-native-upi-payment for all types of upi available or else phonepesdk for only phonepe integration

Packing js file to be inserted into React Native's WebView

I am creating a webview in a react native script, such as
<WebView source="https://www.google.com" />
However, I would like to inject a whole bunch of javascripts into the webview. The scripts to be included is located at let's say additionalScripts.js (which may import a whole bunch of dependencies such as jquery etc.
So intuitive I am trying to do
import additionalScripts from './additionalScripts.js'
<WebView source="https://www.google.com" injectedJavaScript={additionalScripts} />
Firstly it does not work.
Secondly, how do it make sure that the additionalScripts imported has been properly 'webpacked' and 'uglified' ?
Thanks
The problem is that injectedJavaScript needs a string, but the import actually executes the JS file and exports the result as an object.
To load the file as text, you can try something like React Native FS module, I learned about it from this answer.
// ...
import RNFS from require('react-native-fs');
// ...
class MyComponent extends Component {
constructor() {
super();
this.state = {
additionalScripts: null
};
}
componentDidMount() {
RNFS.readFile('./additionalScripts.js', 'utf8')
.then((contents) => {
this.setState({
additionalScripts: contents
});
});
}
render() {
if(!this.state.additionalScripts) {
return null;
}
return <WebView
source="https://www.google.com"
injectedJavaScript={additionalScripts} />;
}
}