hey guys good morning i am having this issue and couldn’t figure out. I am using the new SDK("react-native-purchases": "^4.5.3"), and also EXPO MANAGED FLOW("expo": "~44.0.0"), all updated.
It is always getting in the catch of those functions in the useEffect.
evaluating RNPurchases.isConfigured
This is my code:
useEffect(() => {
const connectRevenueCat = async () => {
Purchases.setDebugLogsEnabled(true)
if (Platform.OS === 'android') {
console.log('entrou 3')
await Purchases.setup('mypass', 'null')
}
}
connectRevenueCat()
const getPackages = async () => {
try {
const offerings = await Purchases.getOfferings()
if (offerings.current !== null) {
setProducts([offerings.current.availablePackages[0].product])
}
} catch (e) {
// put this on screen to version 18
setError(e?.message + 'O meu errinho do bem')
}
}
getPackages()
}, [])
Thanks for any help
Related
I'm making a login using a JWT and deviceStorage, it's working okay but every time I start the app, and with JWT removed from deviceStorage, it start as if already logged in. The problem is that the get method in deviceStorage returns a promise, so I need to either make the get method return null if empty or have my program know if it's a string or a promise
APP.JS
import 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import React, { useState, useEffect } from 'react';
import Login from './src/Pages/Login';
import LoggedIn from './src/Pages/LoggedIn';
import deviceStorage from './src/Service/deviceStorage';
const App = () => {
const [JWT, setJWT] = useState(null);
useEffect(() => {
const checkJWT = () => {
setJWT(deviceStorage.getValue())
}
checkJWT()
}, []
);
const checkJWT = () =>{
if (!JWT || JWT === null || JWT === "") {
return <Login setJWT={setJWT} />
}else if (JWT){
return <LoggedIn JWT={JWT} setJWT={setJWT} />
}
}
return (
<SafeAreaProvider>
{checkJWT()}
</SafeAreaProvider>
)
}
export default App
DEVICESTORAGE
import AsyncStorage from '#react-native-async-storage/async-storage';
const key = 'currentUser';
const deviceStorage = {
async saveItem(value) {
try {
const jsonValue = JSON.stringify(value)
await AsyncStorage.setItem(key, jsonValue);
} catch (error) {
console.log('AsyncStorage Error: ' + error.message);
}
console.log('Done saving Value.')
},
async getValue() {
try {
return await AsyncStorage.getItem(key)
} catch(e) {
console.log('AsyncStorage Error: ' + e.message);
}
console.log('Done getting value.')
},
async removeValue() {
try {
await AsyncStorage.removeItem(key)
} catch(e) {
console.log('AsyncStorage Error: ' + e.message);
}
console.log('Done removing Value.')
}
};
export default deviceStorage;
I hope someone can help me with this
As you pointed out, the get method of deviceStorage returns a promise currently. I think you can do one of these:
If useEffect can accept an async method I think this should work:
useEffect(async () => {
const checkJWT = () => {
setJWT(await deviceStorage.getValue())
}
checkJWT()
}, []);
If not, then something like this should work:
useEffect(() => {
const checkJWT = () => {
deviceStorage.getValue().then(value => setJWT(value));
}
checkJWT()
}, []);
I haven't checked that anywhere if that works, but something along those lines should do the trick. You should make sure that you indeed put a JWT in your setJWT method and not a Promise. Or maybe you could change your setJWT method so it knows, that if it received a promise then you have to wait for the result.
Try out this function :
async getValue() {
try {
let value = null;
value = await AsyncStorage.getItem(key);
return value;
} catch(e) {
console.log('AsyncStorage Error: ' + e.message);
}
console.log('Done getting value.')
}
I dont really understand how setState and state variables update and work in React Native. Im trying to figure out what I did wrong in the code below, because I'm updating my tokenArray variable, but when I console log it in another function it is empty. Please help.
constructor() {
super()
this.state = {
tokenArr: []
}
}
componentDidMount() {
this.grabToken()
}
firebaseInformation = async () => {
var tokens = []
firebase.database().ref(`tokens/`).once('value', snapshot => {
const token = Object.values(snapshot.val());
token.map((item) => {
tokens.push(item.data)
})
return this.setState({
tokenArr: tokens
})
})
}
grabToken = async () => {
this.firebaseInformation()
console.log(this.state.tokenArr)
}
The fix was just to call the grabToken function in my render method instead (I was only calling it from my componentDidMount and didn't understand why it wasn't updating my state variable properly.
Return the array and set the state in componentDidMount() like this
componentDidMount() {
this.firebaseInformation()
.then((arr) => this.setState({ tokenArr: arr }))
.then(this.state.tokenArr);
}
firebaseInformation = async () => {
var tokens = []
firebase.database().ref(`tokens/`).once('value', snapshot => {
const token = Object.values(snapshot.val());
token.map((item) => {
tokens.push(item.data)
})
return tokenArr;
})
}
I am using react native linking component for opening call application.call suggestion dialog get opened but when I click on cancel it does not return me any promise
static makePhoneCall = (mobileNumber) =>
{
let phoneNumber = '';
if (Platform.OS === 'android') {
let userMobile = `tel:${mobileNumber}`
phoneNumber = userMobile;
}
else {
let userMobile = `tel://${mobileNumber}`
phoneNumber = userMobile;
}
Linking.openURL(phoneNumber).then(() => {
alert('success')
}).catch(() => {
alert('failure')
});
return 'default`
}
classname.makePhoneCall(this.state.item.mobileNumber)
I want to know how to handle openUrl Promise with some example, I have share code of what I have done. I am using react native version 0.59.9
You should check to see if theres an app available to handle the url first.
Linking.canOpenURL(phoneNumber)
.then((supported) => {
if (!supported) {
console.log("Can't handle url: " + url);
} else {
return Linking.openURL(url);
}
})
.catch((err) => console.error('An error occurred', err));
I've tried #react-native-community/netinfo to check the internet reachability. But the scenario I want to implement is, suppose if my device is connected to a wifi hotspot from another device and if that device's mobile data is turned off I want to show an offline toast.
componentDidMount() {
NetInfo.addEventListener(status => {
this.props.checkOnlineStatus(
status.isConnected,
status.isInternetReachable
);
this.setState({
isConnected: status.isConnected,
isInternetReachable: status.isInternetReachable
});
});
}
render() {
if (!this.state.isInternetReachable && this.props.isOfflineNoticeVisible) {
return <MiniOfflineSign />;
}
return null;
}
But in this case, when the mobile data of the other device is turned off, it doesn't handle the change.
The non-deprecated way (using functional components) with the #react-native-community/netinfo package is now:
import React, { useEffect } from "react";
import NetInfo from "#react-native-community/netinfo";
useEffect(() => {
return NetInfo.addEventListener(state => {
// use state.isInternetReachable or some other field
// I used a useState hook to store the result for use elsewhere
});
}, []);
This will run the callback whenever the state changes, and unsubscribe when the component unmounts.
These connection types could help: https://github.com/react-native-community/react-native-netinfo#netinfostatetype
Otherwise:
Then to be sure, you are online just implement a fetch with timeout:
export default function(url, options, timeout = 5000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject("timeout"), timeout)),
]);
}
Then use it like this:
fetchWithTimeout(url, options)
.then(resp => {
if (resp.status === 200) {
let json = resp.json().then(j => {
return j;
});
})
.catch(ex => {
// HANDLE offline usage
if (ex === "timeout") return true;
//ANY OTHER CASE RETURN FALSE
return false;
}
async function InternetCheck() {
const connectionInfo = await NetInfo.getConnectionInfo();
if (connectionInfo.type === 'none') {
alert('PLEASE CONNECT TO INTERNET');
} else {
//navigate to page or Call API
}
}
I am a beginner at react-native.
I trying to retrieve data that stored from screen1.js in Screen2.js but I failed.
I have import Asyncstorage from react-native for both .js
This how I store variable from screenone.js :
class screenone extends Component {
state = {
oldpin: '000000',
newpin: '',
secpin: '',
};
onPressButton = () => {
if (this.state.newpin == this.state.secpin) {
this.setState(
{ oldpin: this.state.newpin },
async() => await this.storeData());
}
else {
ToastAndroid.show("Password Unmatched", ToastAndroid.SHORT);
}
}
storeData = async () =>{
const {oldpin} = this.state;
let pin : oldpin;
try{
await AsyncStorage.setItem('mypin',pin);
ToastAndroid.show("Password Changed", ToastAndroid.SHORT);
}
catch (err){
console.warn(err)
}}
....
This is how I trying to retrieve data in screentwo.js:
class screentwo extends Component {
constructor(props) {
super(props);
this.onComplete = this.onComplete.bind(this);
this.state = {
pin: ''
};
}
retrieveData = async (mypin) => {
try {
let value = await AsyncStorage.getItem(mypin);
if (value !== null) {
console.log(value);
this.setState({
pin: value})
}
} catch (error) {
console.warn(err)
}
}
onComplete(inputtedPin, clear) {
retrieveData();
if (inputtedPin !== this.state.pin) {
ToastAndroid.show("Incorrect Pin", ToastAndroid.SHORT);
clear();
} else {
ToastAndroid.show("Pin is correct", ToastAndroid.SHORT);
clear();
this.props.navigation.navigate("Dashboard");
}}
....
Error:
Reference Error: ReferenceError:Can't find variable:retrieveData
Am I using the right way to stored and retrieve data?
Any suggestion?
Thank you.
There are a couple of issues that I can see with your code.
Firstly the retrieveData() function. It is asynchronous and should be called with await also you are getting the error: Reference Error: ReferenceError:Can't find variable:retrieveData because you haven't used this
So ideally you should call it await this.retrieveData();
There are a few more issues with this function. You use the parameter mypin but don't seem to pass any parameter to the function when you call it. Fixing this issue you should call retreiveData() like this:
await this.retrieveData('mypin');
Or you could remove passing the paramater altogether, which I will show how to do in my refactor below.
Finally you call retreiveData every time you check the inputtedPin this isn't that efficient, it is asynchronous so it may take some time, and secondly it also takes time for the setState function to complete, which means that the state may not have updated in time when you go to check it against the inputtedPin, meaning that you are checking the inputtedPin against the wrong value.
Code Refactor
This is how I would refactor your component.
Refactor retrieveData so that it no longer takes a parameter and the key is hardcoded in the .getItem
In the componentDidMount get the value of the pin from AsyncStorage and save it to state.
Remove the retrieveData call from onComplete
Here is the refactor
retrieveData = async () => { // parameter have been removed
try {
let value = await AsyncStorage.getItem('mypin'); // notice I am now passing the key as a string not as a parameter
if (value !== null) {
console.log(value);
this.setState({ pin: value })
}
} catch (error) {
console.warn(err)
}
}
// here we call the refactored retrievedData which will set the state.
async componentDidMount () {
await this.retrieveData();
}
onComplete(inputtedPin, clear) {
// we remove the call to retrieveData as we have already gotten the pin in the componentDidMount
if (inputtedPin !== this.state.pin) {
ToastAndroid.show("Incorrect Pin", ToastAndroid.SHORT);
clear();
} else {
ToastAndroid.show("Pin is correct", ToastAndroid.SHORT);
clear();
this.props.navigation.navigate("Dashboard");
}
}
only replace
retrieveData();
to
this.retrieveData();
When you call async method from a caller method that method also become async Try prefix
async onComplete () { await this.retrieveData() }