Related
I have to integrate Stripe with my React Native Application this phone application is a phone version of a desktop application where stripe is already being integrated and works fine so the backend is already been implemented. I wanted to use the context i used i nthe react js application however the useElementwas not available in stripe/stripe-react-native however after some reasearch i figured it didn't matter if i used the #stripe/stripe-js library my problem now is i keep getting the error: Could not find Elements context; You need to wrap the part of your app that calls useElements() in an <Elements> provider. However i already wrapped the form in an provider this is my checkoutForm.js:
import { useNavigation } from '#react-navigation/native';
import
React,
{ useState,
useEffect, useRef }
from 'react'
import {
View,
Text,
SafeAreaView,
StatusBar,
StyleSheet,
TouchableOpacity,
ScrollView,
Image,
Pressable ,
TextInput,
Alert}
from 'react-native';
import Icon from '../components'
import { COLORS } from '../constants';
import { useStateContext } from '../context/StateContext';
import { ProductCarousel } from '../../components';
import { useElements, Elements} from "#stripe/react-stripe-js"
import { CardField, useConfirmPayment, useStripe, } from '#stripe/stripe-react-native';
import { Button } from 'react-native-elements';
const CheckoutForm = () => {
const navigation = useNavigation();
const [isDeliveryAddressOpen, setIsDeliveryAddressOpen] = useState(false);
const [isContactNumberOpen, setIsContactNumberOpen] = useState(false);
const [isDeliveryInstructionsOpen, setIsDeliveryInstructionsOpen] = useState(false);
const [isCartItemsOpen, setIsCartItemsOpen] = useState(false);
const [isPaymentInfoOpen, setIsPaymentInfoOpen] = useState(false);
//const { confirmPayment, loading } = useConfirmPayment();
const [success, setSuccess ] = useState(false)
const stripe = useStripe()
const elements = useElements()
const cardElement = useRef(null);
const { totalPrice, cartItems } = useStateContext();
const [fullName, setFullName] = useState('');
const [email, setEmail] = useState('');
const [address, setAddress] = useState('');
const [address2, setAddress2] = useState('');
const [state, setState] = useState('');
const [city, setCity] = useState('');
const [zipCode, setZipCode] = useState('');
const [primaryNumber, setPrimaryNumber] = useState('');
const [SecondaryNumber, setSecondaryNumber] = useState('');
const [DeliveryInstructions, setDeliveryInstructions] = useState('');
const [isProcessing, setIsProcessing] = useState(false);
const [isError, setIsError] = useState(false);
//const [cardDetails, setCardDetails] = useState('')
const toggleDeliveryAddress = () => {
setIsDeliveryAddressOpen(!isDeliveryAddressOpen);
};
const toggleContactNumber = () => {
setIsContactNumberOpen(!isContactNumberOpen);
};
const toggleDeliveryInstructions = () => {
setIsDeliveryInstructionsOpen(!isDeliveryInstructionsOpen);
};
const toggleCartItems = () => {
setIsCartItemsOpen(!isCartItemsOpen);
};
const togglePaymentInfo = () => {
setIsPaymentInfoOpen(!isPaymentInfoOpen);
};
//const navigate = useNavigate();
const carts = {
status: 'pending',
items: (cartItems),
address,
fullName,
zipCode,
state,
city,
DeliveryInstructions,
primaryNumber,
SecondaryNumber,
totalPrice
}
const handleCheckout = async () => {
const response = await fetch('/create_cart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(carts),
});
if(response.statusCode === 500) return;
// eslint-disable-next-line
const data = await response.json();
console.log('presseddddd', data)
}
/*========================================================*/
const handleSubmit = async () => {
const {error, paymentMethod} = await stripe.createPaymentMethod({
type: "card",
card: elements.getElement(CardField),
billing_details: {
name: fullName,
phone: primaryNumber,
email: email,
address: {
city: city,
line1: address,
state: state,
postal_code: zipCode
}
},
})
if(!error) {
try {
const {id} = paymentMethod
const carts = {
id,
amount: totalPrice,
confirm: true,
currency: 'CAD'
}
setIsProcessing(true);
const response = await fetch('/create-payment-intent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(carts),
});
if(response.status === 200) {
console.log(response.status)
console.log("Successful payment")
setSuccess(true)
}
const data = await response.json();
if(response.status >= 400) {
console.log(response.status)
console.log(data.error.split(':').pop())
setIsError(data.error)
}
} catch (error) {
console.log("Error", error)
}
} else {
console.log(error.message)
}
setIsProcessing(false)
//navigate('/');
}
return (
<View style={styles.container}>
<View style={styles.insideContainer}>
<TouchableOpacity style={styles.titleContainer} onPress={togglePaymentInfo}>
<Text style={styles.title}>Payment Info</Text>
{!isPaymentInfoOpen ?
<Icon icon ='add-outline' color='#000' size={20}/>
: <Icon icon ='remove-outline' color='#000' size={20}/>
}
</TouchableOpacity>
{isPaymentInfoOpen && (
<View style={styles.containercollapsed}>
<View style={{width: '98%'}}>
<CardField
ref={cardElement}
postalCodeEnabled={false}
placeholders={{
number: '4242 4242 4242 4242',
}}
cardStyle={{
backgroundColor: '#FFFFFF',
textColor: '#000000',
borderColor: COLORS.lightGray2,
borderWidth: 1,
borderRadius: 4
}}
style={{
width: '100%',
height: 50,
}}
onCardChange={(cardDetails) => {
}}
onFocus={(focusedField) => {
}}
/>
</View>
</View>
)}
</View>
<View style={styles.PaybuttonView}>
<Button
title="Pay"
onPress={ () => handleSubmit()}
/*disabled={loading}
loading={loading}*/
/>
{/*<Pressable style={styles.Paybutton} onPress={() => {handleCheckout(); handlePayPress()} }>
<Text style={{textAlign: 'center', fontSize: 20, color: '#FFFF', textTransform: 'uppercase'}}>Checkout</Text>
</Pressable>*/}
</View>
</View>
)
}
export default CheckoutForm
this is my StripeForm.js :
import React from 'react'
import {Elements} from "#stripe/react-stripe-js"
import CheckoutForm from './CheckoutForm';
import { loadStripe } from "#stripe/stripe-js"
const stripePromise = loadStripe(i removed the key but this is the key's place);
export const StipeForm = () => {
return (
<Elements stripe={stripePromise}>
<CheckoutForm />
</Elements>
)
}
To initialize Stripe to be used with the Stripe React Native SDK you need to use either StripeProvider or initStripe. See the docs here. You can't use the React Stripe.JS library initialize Stripe for the React Native SDK.
enter image description here
Above is the image description of what I want to achieve. I already implemented all the layers but I have a problem in automatically updating userContext. I have to refresh the userContext.js page manually to all the information across the app get updated as I want.
My DataBase.js looks like this
import React, { createContext, useState, useEffect,useCallback} from "react";
// create context
const UserContext = createContext();
const UserContextProvider = ({children}) => {
// the value that will be given to the context
var data = global.userSignedUp
const [UserDetails, SetUserDetails] = useState(data)
const [loadingUser, setLoadingUser] = useState(true);
// fetch a user from a fake backend API
const fetchUser = async () => {
// this would usually be your own backend, or localStorage
// for example
var name = global.userSignedUp.username
var index= global.userSignedUp.id
console.log('This the response from DataBase.js',UserDetails)
const data= await fetch('XXXXXX/api/userprofile/'+UserDetails.id+'/',{
method : 'GET',
header : {
Accept : 'application/json',
'Content-Type' : 'application/json'
}
}).then(async res =>{
const response =await res.json()
console.log('This the response from DataBase.js',response)
SetUserDetails(response)
})
//
};
useEffect(() => {
fetchUser();
}, []);
return (
// the Provider gives access to the context to its children
<UserContext.Provider value={[UserDetails, SetUserDetails]}>
{children }
</UserContext.Provider>
);
};
export { UserContext, UserContextProvider };
I defined one global variable index that get updated depending on the user ID from the sign in page and passed inside the Database.js
const onSignInPressed =(logindata)=>{
const username = logindata.username
const password =logindata.password
// state={
// credentials :{username : username, password: password}
// }
fetch('http://XXXXX/auth/',{
method:'POST',
headers:{'Content-Type':'application/json'},
body : JSON.stringify({username:username, password:password})
}).then (async data =>{
const DataResponse =await data.json()
//console.log(DataResponse)
if (data.status===200){
fetch('http://XXXX/api/userprofile',{
method : 'GET',
header : {
Accept : 'application/json',
'Content-Type' : 'application/json'
}
}).then(async res =>{
const response =await res.json()
for (let i=0; i < response.length;i++){
if (response[i].user=== username){
userSignedUp=response[i]
console.log('this is the user Signed up Id',userSignedUp)
navigation.navigate('HomeProfile')
;
}
}
})
}
else{
Alert.alert('Invalid User!','Username or password is incorrect,')
}
})
}
in my HomeProfile.js I can get all the data from UserContext and it workds fine.
Now in my EditProfile.js I have this :
import React , {useState,useContext,useEffect,useCallback} from 'react'
import {SocialIcon} from 'react-native-elements'
import { ImageBackground, View, Text, Image, StyleSheet, useWindowDimensions,Alert} from 'react-native'
import { icons,images, COLORS, SIZES } from '../constants';
import {CustomInput} from '../Component/CustomInput';
import CustomButton from '../Component/CustomButton';
import {useNavigation} from '#react-navigation/native';
import {useForm, Controller} from 'react-hook-form';
import { UserContext, UserContextProvider } from "./MobileDatabase/DataBase";
const EditProfile = () => {
return (
<UserContextProvider>
<EditProfilePage />
</UserContextProvider>
);
}
const EditProfilePage = () => {
const {control,handleSubmit,watch} = useForm();
const {height}= useWindowDimensions();
const navigation =useNavigation();
const newpwd = watch('NewPassword')
const [UserDetails, SetUserDetails]= useContext(UserContext);
let OldUsername=UserDetails.user
let DataFromServer=UserDetails
const onSavePressed = async (EditData) =>{
console.log(EditData)
const uploadData =new FormData();
uploadData.append('username',EditData.ChangeUsername)
let editData= await fetch('http://192.168.56.1:8000/api/users/'+OldUsername+'/',{
method:'PATCH',
headers:{Accept: 'application/json',
'Content-Type': 'multipart/form-data; '},
body :uploadData,
})
let EditDataResponseJson = await editData.json();
console.log(EditDataResponseJson)
SetUserDetails({...UserDetails, user:EditDataResponseJson.username})
UserContextProvider(EditDataResponseJson)
navigation.navigate('HomeProfile')
}
return (
<View style={styles.root}>
<Image
source ={{uri:UserDetails.Profileimage}}
style={[styles.logo]}
//resizeMode='contain'
/>
<Text style={{fontWeight:'bold',
//position:"absolute",
flex:1,
fontSize: 20,
top:'3%',
maxWidth:200,
alignSelf:'center' }}>{UserDetails.user}</Text>
<CustomInput placeholder ='Change UserName'
name="ChangeUsername"
control={control}
rules={{required: 'Username is required',
minLength:{
value:3,
message :'Username should be at least 3 characters long'
}
}}
// value={username}
// setValue={setUsername}
/>
<CustomInput placeholder= 'Change Password'
name ='NewPassword'
control={control}
rules={{required: 'New password is required'}}
// value={password}
// setValue={setPassword}
secureTextEntry={true}
/>
<CustomInput placeholder= 'Confirm Password'
name ='RepeatNewPassword'
control={control}
rules={{
validate: value => value === newpwd || 'Password do not match'
}}
// value={password}
// setValue={setPassword}
secureTextEntry={true}
/>
<View style ={styles.Signup}>
<CustomButton text= 'Save Changes' onPress={handleSubmit(onSavePressed)} />
</View>
</View>
)
}
const styles = StyleSheet.create({
root :{
//alignItems :'center',
paddingTop :'60%',
flex: 1,
},
cover:{
flex:1,
justifyContent: 'center',
},
logo:{
position :'absolute',
top:'10%',
alignSelf:'center',
justifyContent:'center',
alignItems: 'center',
width: 150,
height: 150,
borderRadius: 400/ 2,
},
Signup:{
marginTop: '20%',
}
})
export default EditProfile
When I update the Username for example, it only changes inside EditPage.js but not in HomeProfile.js event thought I update the SetUserDetails. The only way to see the updated data is to refresh the Database.js.
I am very much stuck since a month now and hope for a help here.
Thank you!!
I have this page (screen) that receives via Params an ID number, in this Screen, I try to call an Action Function from my Action (reducer) file and gets an API call, I thought I didn't get any information in the Array from that call, I believe that the issue was in the Call, but I put a Console log after the declaration on the Action Function, but it didn't print so I think it didn't access to that function, so I believe the issue is in the Call of that function via Dispatch.
I even tried to put a Breakpoint inside the UseEfect where I call the Function that calls the Dispatch Function but it never breaks I'm not sure where is the error, this is the Code:
Screen (where I suspect the issue is):
```import React, {useState, useCallback, useEffect} from 'react';
import { ScrollView, Text, Image, StyleSheet, View } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
const ProductDetailScreen = props => {
const playerId = props.route.params.id;
const estadId = props.route.params.statId;
const selectedPlayer = useSelector(state => state.jugadores.availablePlayers.find(prod => prod.id === playerId));
const [isLoading, setIsLoading] = useState(false);
const [isRefreshing, setIsRefreshing] = useState(false);
const [error, setError] = useState();
const goles = useSelector(state => state.jugadores.playerGoals);
const dispatch = useDispatch();
const loadEstad = useCallback (async (param) => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(userActions.fetchEstadistica(param));
} catch (err){
setError(err.message);
}
setIsRefreshing(false);
}, [dispatch, setIsLoading, setError]);
useEffect(() => {
setIsLoading(true);
loadEstad(estadId).then(() => {
setIsLoading(false);
});
}, [dispatch, loadEstad]);
console.log(estadId);
console.log(goles);
return (
<ScrollView>
<Image style={styles.image} source={{ uri: selectedPlayer.imagen }} />
<View style={styles.dataContainer}>
<Text style={styles.description}>Numero: <Text style={styles.subtitle}>{selectedPlayer.numero}</Text></Text>
<Text style={styles.description}>Nombre Completo: <Text style={styles.subtitle}>{selectedPlayer.nombre_completo}</Text></Text>
<Text style={styles.description}>Posicion: <Text style={styles.subtitle}>{selectedPlayer.posicion}</Text> </Text>
<Text style={styles.description}>Edad: <Text style={styles.subtitle}>{selectedPlayer.edad}</Text></Text>
<Text style={styles.description}>Nacionalidad: <Text style={styles.subtitle}>{selectedPlayer.nacionalidad}</Text></Text>
</View>
</ScrollView>
);
}
;
export const screenOptions = navData => {
return {
headerTitle: navData.route.params.nombre,
}
};
const
styles = StyleSheet.create({
image: {
width: '100%',
height: 300,
},
subtitle: {
fontSize: 16,
textAlign: 'justify',
marginVertical: 20,
fontWeight:'normal',
},
description: {
fontSize: 16,
textAlign: 'center',
marginVertical: 20,
fontWeight: 'bold',
},
dataContainer:{
width: '80%',
alignItems: 'center',
marginHorizontal: 40,
},
actions: {
marginVertical: 10,
alignItems: 'center',
},
});
export default ProductDetailScreen
;```
This is my Action File:
import ResultadoEstadistica from '../../models/estadistica/resultadoEstadistica';
import PlayerEstadistica from '../../models/estadistica/playerEstatisticData';
import Cards from '../../models/estadistica/cards';
import Games from '../../models/estadistica/games';
import Goals from '../../models/estadistica/goals';
export const SET_JUGADORES = 'SET_JUGADORES';
export const SET_ESTADISTICA = 'SET_ESTADISTICA';
export const fetchJugadores = () => {
return async (dispatch) => {
//any async code here!!!
try {
const response = await fetch(
'https://alianzafc2021-default-rtdb.firebaseio.com/jugadores.json'
);
if (!response.ok) {
throw new Error('Algo salio Mal!');
}
const resData = await response.json();
const loadedJugadores = [];
for (const key in resData) {
loadedJugadores.push(
new Jugador(
key,
resData[key].altura,
resData[key].apellido,
resData[key].edad,
resData[key].fecha_nacimiento,
resData[key].iso_code,
resData[key].imagen,
resData[key].lugar_nacimiento,
resData[key].nacionalidad,
resData[key].nombre_completo,
resData[key].nombre_corto,
resData[key].nombres,
resData[key].numero,
resData[key].pais,
resData[key].peso,
resData[key].player_id,
resData[key].posicion
)
);
}
dispatch({ type: SET_JUGADORES, players: loadedJugadores });
} catch (err) {
throw err;
}
};
}
export const fetchEstadistica = player_id => {
return async (dispatch) => {
//any async code here!!!
try {
const response = await fetch(
`https://api-football-v1.p.rapidapi.com/v2/players/player/${player_id}.json`,
{
method: 'GET',
headers: {
'x-rapidapi-key': Here goes my API KEY,
'x-rapidapi-host': 'api-football-v1.p.rapidapi.com',
'useQueryString': 'true'
}
}
);
if (!response.ok) {
throw new Error('Algo salio Mal!');
}
const resData = await response.json();
const loadesApiResult = [];
console.log('***Impresion desde la accion***');
console.log(resData);
console.log('***Fin de Impresionc***');
//Arrays de la Estadistica del Jugador
const loadedEstadistica = [];
const loadedCards = [];
const loadedGoals = [];
const loadedGames = [];
for (const key in resData) {
loadesApiResult.push(
new ResultadoEstadistica(
resData[key].results,
resData[key].players
)
);
}
const apiData = loadesApiResult.players;
for (const key in apiData) {
loadedEstadistica.push(
new PlayerEstadistica(
apiData[key].player_id,
apiData[key].player_name,
apiData[key].firstname,
apiData[key].lastname,
apiData[key].number,
apiData[key].position,
apiData[key].age,
apiData[key].birth_date,
apiData[key].birth_place,
apiData[key].birth_country,
apiData[key].nationality,
apiData[key].height,
apiData[key].weight,
apiData[key].injured,
apiData[key].rating,
apiData[key].team_id,
apiData[key].team_name,
apiData[key].league_id,
apiData[key].league,
apiData[key].season,
apiData[key].captain,
apiData[key].shots,
apiData[key].goals,
apiData[key].passes,
apiData[key].duels,
apiData[key].dribbles,
apiData[key].fouls,
apiData[key].cards,
apiData[key].penalty,
apiData[key].games,
apiData[key].substitutes,
)
);
}
const playerDataGames = loadedEstadistica.games;
for (const key in playerDataGames) {
loadedGames.push(
new Games(
playerDataGames[key].apperences,
playerDataGames[key].minutes_played,
playerDataGames[key].lineups
)
);
};
const playerDataGoals = loadedEstadistica.goals;
for (const key in playerDataGoals) {
loadedGoals.push(
new Goals(
playerDataGoals[key].total,
playerDataGoals[key].conceded,
playerDataGoals[key].assists,
playerDataGoals[key].saves
)
);
};
const playerDataCards = loadedEstadistica.cards;
for (const key in playerDataCards) {
loadedCards.push(
new Cards(
playerDataCards[key].yellow,
playerDataCards[key].yellowred,
playerDataCards[key].red
)
);
};
dispatch({ type: SET_ESTADISTICA, estadistica: loadesApiResult, goles: loadedGoals, juegos: loadedGames, tarjetas: loadedCards });
} catch (err) {
throw err;
}
};
};```
Finally this is my Redux Reducer just incase:
import { SET_JUGADORES, SET_ESTADISTICA } from "../actions/jugadores";
const initialState = {
availablePlayers: [],
estadistica: [],
playerGoals: [],
playerCards: [],
playerGames: [],
}
export default (state = initialState, action) => {
switch (action.type) {
case SET_JUGADORES:
return {
...state,
availablePlayers: action.players,
};
case SET_ESTADISTICA:
return{
...state,
estadistica: estadistica,
playerGoals: action.goles,
playerCards: action.tarjetas,
playerGames: action.juegos
};
}
return state;
};
Sorry for the Format but is giving me some issues; Any Ideas what my Be the Problem?
Thank you.
there are a few issues with your screen code, so i recommend simplifying the logic to make sure it works before adding anything thing else.
replace this:
const loadEstad = useCallback (async (param) => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(userActions.fetchEstadistica(param));
} catch (err){
setError(err.message);
}
setIsRefreshing(false);
}, [dispatch, setIsLoading, setError]);
useEffect(() => {
setIsLoading(true);
loadEstad(estadId).then(() => {
setIsLoading(false);
});
}, [dispatch, loadEstad]);
console.log(estadId);
console.log(goles);
with this:
useEffect(()=>{
if (estadId) dispatch(userActions.fetchEstadistica(estadId));
},[estadId]);
Assuming your reducer/action code is correct, then this should call the api everytime the params estadId changes. The loading/refresh should be set in the reducer instead on the screen component.
a few things to keep in mind:
Don't await for dispatch.
console.log on state variables outside of promise resolving code block won't work.
This below won't work. instead, you should set the loading variable as a redux variable that gets updated after the API comes back with data.
loadEstad(estadId).then(() => {
setIsLoading(false);
});
I am trying to make a dynamic form. The user must enter the required count of fields in the first text field. After that, I add the entered count to the state and render all the fields. But in "onChangeText" the previous state value is returned. At the same time, if I click on the button, the current state value is returned?
import React, {useState} from "react";
import {Button, TextInput, View, StyleSheet} from "react-native";
export const TestScreen = () => {
const initialState: any = {
num: null,
inputs: null
};
const [state, setState] = useState(initialState);
const changeNum = (num = null) => {
const inputs = [];
if (num) {
for (let i = 0; i < num; i++) {
inputs.push(
<TextInput
key={i.toString()}
style={styles.input}
onChangeText={changeNewInput}
/>
)
}
}
setState({num, inputs})
};
const changeNewInput = (e) => {
console.log(state.num)
};
return (
<View>
<TextInput onChangeText={changeNum} style={{...styles.input, borderColor: 'red'}}/>
{state.inputs}
<Button title={'see count'} onPress={() => console.log(state.num)}/>
</View>
)
};
const styles = StyleSheet.create({
input: {
borderWidth: 1,
borderColor: 'black',
marginBottom: 5
}
});
the state update using the updater provided by useState hook is asynchronous. That's why you see previous value of your state when you call changeNewInput method after setState. If you want to see your state is updated you can use, useEffect.
useEffect(() => {
console.log(state.num)
}, [state]);
I'm using my code example
Create a new useEffect and set a new State inside
OLD STATE const [comment, setComment] = useState('')
NEW STATE const [newData, setNewData] = useState(null)
onChangeText={text => setComment(text)}
useEffect(() => {
setNewData(comment)
},[comment])
I'm beginner in React Native, I'm using expo I want to ask user for permission to access location if user granted the permission it will check if phone location from setting is on or not if it is on then it will give it's current location and if the app is close or running in background it will still give location
I have tried but it's not working
import React, { Component } from "react";
import {
Platform,
Text,
View,
StyleSheet,
Linking,
Button,
AppState
} from "react-native";
import Constants from "expo-constants";
import * as TaskManager from "expo-task-manager";
import * as Location from "expo-location";
import * as Permissions from "expo-permissions";
import * as IntentLauncher from "expo-intent-launcher";
import { Alert, NavigationActions } from "react-native";
import Modal from "react-native-modal";
const LOCATION_TASK_NAME = "background-location-task";
export default class LocationScreen extends Component {
state = {
location: null,
errorMessage: null,
};
componentDidMount = async () => {
await Location.startLocationUpdatesAsync(LOCATION_TASK_NAME, {
accuracy: Location.Accuracy.Balanced
});
render() {
let text = "Waiting..";
if (this.state.errorMessage) {
text = this.state.errorMessage;
} else if (this.state.location) {
text = JSON.stringify(this.state.location);
}
return (
<View style={styles.container}>
<Text style={styles.paragraph}>{text}</Text>
</View>
);
}
}
TaskManager.defineTask(LOCATION_TASK_NAME, handel);
export async function handel({ data, error }) {
try {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
this.setState({
errorMessage: "Permission to access location was denied"
});
return;
} else {
if (data) {
const { locations } = data;
const location = locations.map(location => {
let newLocation = Location.reverseGeocodeAsync(location.coords).then(
data => {
let maplocation = data.map(location => {
console.log(location);
console.log(location.city);
});
}
);
});
}
}
} catch (error) {
let status = Location.getProviderStatusAsync();
if (!status.locationServiceEnabled) {
const { navigation } = this.props;
navigation.navigate("Login");
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
paddingTop: Constants.statusBarHeight,
backgroundColor: "#ecf0f1"
},
paragraph: {
margin: 24,
fontSize: 18,
textAlign: "center"
}
});
This is only working if location is on. It's not asking for permission if location is off or not granted