I Can't get my exact location using expo-location - javascript

THE CODE USING REACT-NATIVE AND EXPO-LOCATION:
import {
View,
Text,
Alert,
SafeAreaView,
RefreshControl,
StyleSheet,
ActivityIndicator,
ScrollView
} from 'react-native';
import React, {
useEffect,
useState
} from 'react';
import * as Location from 'expo-location'
const openWeatherKey = 'cbb62d0f2653b471dbf6ca28aebb813f'
let url = `http://api.openweathermap.org/data/2.5/onecall?&units=metric&exclude=minutely&appid=${openWeatherKey}`
const Weather = () => {
const [forecast, setForecast] = useState(null)
const [refreshing, setRefreshing] = useState(false)
const loadForecast = async () => {
setRefreshing(true)
const {
status
} = await Location.requestForegroundPermissionsAsync();
if (status !== 'granted') {
Alert.alert('Permission to acces location was denied')
}
let location = await Location.getCurrentPositionAsync({
enableHighAccuracy: true
})
const response = await fetch(`${url}&lat=${location.coords.latitude}&lon=${location.coords.longitude}`)
const data = await response.json()
if (!response.ok) {
Alert.alert('error something went wrong')
} else {
setForecast(data);
}
setRefreshing(false)
}
useEffect(() => {
loadForecast()
}, [])
if (!forecast) {
return (
<SafeAreaView style={styles.loading}>
<ActivityIndicator size='large'/>
</SafeAreaView>
)
}
const current = forecast.current.weather[0]
return (
<SafeAreaView style={styles.container}>
<ScrollView
refreshControl={
<RefreshControl
refreshing={refreshing} onRefresh={() => loadForecast()}/>
}
style={{marginTop:50}}
>
<Text style={styles.title}>
Current Weather
</Text>
<Text style={{alignItems:'center', textAlign:'center'}}>
Your Location
</Text>
<View>
</View>
</ScrollView>
</SafeAreaView>
)
}
export default Weather
)
THE ERROR: 'Error something went wrong'
But i dont understand why he is not able to get the location?
Does somebody know the answer? i think it goes wrong at const response. Also when i use the standard Code for gettting a location from expo-location docs it works?

Related

React native undefined in not an object evaluation props.route.params.source

Hello I'm a beginner in react native, and I'm trying to get the URI of the video picked from Galerie and use it in another component, I'm testing it with console log but this error is appearing
undefined in not an object evaluation props.route.params.source
this is the page that the video will be picked from Galerie:
import React, { useEffect, useState } from 'react'
import { View, Text, TouchableOpacity, Image } from 'react-native'
import { Camera } from 'expo-camera'
import { Audio } from 'expo-av'
import * as ImagePicker from 'expo-image-picker'
import * as MediaLibrary from 'expo-media-library'
import * as VideoThumbnails from 'expo-video-thumbnails';
import { useIsFocused } from '#react-navigation/core'
import { Feather } from '#expo/vector-icons'
import styles from './styles'
import { useNavigation } from '#react-navigation/native'
export default function CameraScreen() {
const [hasCameraPermissions, setHasCameraPermissions] = useState(false)
const [hasAudioPermissions, setHasAudioPermissions] = useState(false)
const [hasGalleryPermissions, setHasGalleryPermissions] = useState(false)
const [cameraRef, setCameraRef] = useState(null)
const [cameraType, setCameraType] = useState(Camera.Constants.Type.back)
const [cameraFlash, setCameraFlash] = useState(Camera.Constants.FlashMode.off)
const [isCameraReady, setIsCameraReady] = useState(false)
const isFocused = useIsFocused()
const navigation = useNavigation()
useEffect(() => {
(async () => {
const cameraStatus = await Camera.requestCameraPermissionsAsync()
setHasCameraPermissions(cameraStatus.status == 'granted')
const audioStatus = await Audio.requestPermissionsAsync()
setHasAudioPermissions(audioStatus.status == 'granted')
const galleryStatus = await ImagePicker.requestMediaLibraryPermissionsAsync()
setHasGalleryPermissions(galleryStatus.status == 'granted')
})()
}, [])
const recordVideo = async () => {
if (cameraRef) {
try {
const options = { maxDuration: 60, quality: Camera.Constants.VideoQuality['480'] }
const videoRecordPromise = cameraRef.recordAsync(options)
if (videoRecordPromise) {
const data = await videoRecordPromise;
const source = data.uri
/*let sourceThumb = await generateThumbnail(source)*/
/*navigation.navigate('savePost', { source, sourceThumb })*/
}
} catch (error) {
console.warn(error)
}
}
}
const stopVideo = async () => {
if (cameraRef) {
cameraRef.stopRecording()
}
}
const pickFromGallery = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Videos,
allowsEditing: true,
aspect: [16, 9],
quality: 1
})
if (!result.cancelled) {
let sourceThumb = await generateThumbnail(result.uri)
navigation.navigate('AddProduct', {source : result.uri})
}
}
if (!hasCameraPermissions || !hasAudioPermissions || !hasGalleryPermissions) {
return (
<View></View>
)
}
return (
<View style={styles.container}>
{isFocused ?
<Camera
ref={ref => setCameraRef(ref)}
style={styles.camera}
ratio={'16:9'}
type={cameraType}
flashMode={cameraFlash}
onCameraReady={() => setIsCameraReady(true)}
/>
: null}
<View style={styles.sideBarContainer}>
<TouchableOpacity
style={styles.sideBarButton}
onPress={() => setCameraType(cameraType === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back)}>
<Feather name="refresh-ccw" size={24} color={'white'} />
<Text style={styles.iconText}>Flip</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.sideBarButton}
onPress={() => setCameraFlash(cameraFlash === Camera.Constants.FlashMode.off ? Camera.Constants.FlashMode.torch : Camera.Constants.FlashMode.off)}>
<Feather name="zap" size={24} color={'white'} />
<Text style={styles.iconText}>Flash</Text>
</TouchableOpacity>
</View>
<View style={styles.bottomBarContainer}>
<View style={{ flex: 1 }}></View>
<View style={styles.recordButtonContainer}>
<TouchableOpacity
disabled={!isCameraReady}
onLongPress={() => recordVideo()}
onPressOut={() => stopVideo()}
style={styles.recordButton}
/>
</View>
<View style={{ flex: 1 }}>
<TouchableOpacity
onPress={() => pickFromGallery()}
style={styles.galleryButton}>
</TouchableOpacity>
</View>
</View>
</View>
)
}
and this is the other page where I want to retrieve the video URI:
import { View, Text } from 'react-native'
import React from 'react'
export default function AddProductScreen(props) {
console.log(props.route.prams.source)
return (
<View>
<Text>AddproductScreen</Text>
</View>
)
}
Maybe is a misspelling? you have console.log(props.route.prams.source) instead of console.log(props.route.params.source)

Display of API results with forEach in React Native

I'm trying to display data from an api and cant get a hold of using the forEach method correctly to show all the data at the same time. The API is working correctly. Here's the code:
import React, {useEffect, useState} from 'react'
import { Text, View, ActivityIndicator, ScrollView } from 'react-native'
import axios from '../../utils/axios'
//import CurrencyPair from '../../CurrencyPair'
function HomeScreen() {
const [data, setData] = useState([])
const [isLoading, setIsloading] = useState(true)
useEffect(() => {
const fetchpairs = async() => {
const result = await axios.get('/v3/accounts/{AccountId}/pricing?instruments=EUR_USD%2CUSD_CAD')
console.log(result.data)
setData(result.data)
setIsloading(false)
}
fetchpairs()
}, [])
if(isLoading) {
return (
<ActivityIndicator size="large"/>
)
}
else
return (
<ScrollView>
{[data].map((data) => (
data.forEach(data =>{
<Text>{JSON.stringify(data.prices[0].instrument)}
{JSON.stringify(data.prices[0].closeoutAsk)}
{JSON.stringify(data.prices[0].closeoutBid)}
</Text>
})
))}
</ScrollView>
)
}
export default HomeScreen
Map is already taking care of forEach function
<ScrollView>
{[data].map((item,i) => {
return(<Text key={i}>{JSON.stringify(item.prices[0].instrument)}
{JSON.stringify(item.prices[0].closeoutAsk)}
{JSON.stringify(item.prices[0].closeoutBid)}
</Text>
)}
)}
</ScrollView>

why my react native component keep refreshing?

hi i am trying to build react native app i am using expo
i build a screen to show data and calculate a number using hooks
but i face that my component keep rendering so i cant press in the buttons easily , which lead me to can't calculate the number ,
this is my code how i can stop this continuous refreshing
if i but console statements inside the component it keep printing in console and not stop
import React, { useState, useEffect } from "react";
import { AsyncStorage } from "react-native";
import { Button } from "react-native-paper";
import axios from "axios";
import { View, Text, TextInput, StyleSheet } from "react-native";
export default function Confirm() {
const [info, setInfo] = useState([]);
const [value, onChangeText] = React.useState("0");
const [total, setTotal] = useState("0");
const [selectedLocation, setSelectedLocation] = useState({});
try {
//Retrieving user token, reserved nanny information and user location value from AsyncStorage
AsyncStorage.multiGet(["token", "nany", "location"]).then((res) => {
var nany = JSON.parse(res[1][1]);
var location = JSON.parse(res[2][1]);
setInfo(nany);
console.log("hi3");
setSelectedLocation(location);
});
} catch (error) {
throw error;
}
const onSubmit = () => {
axios
.post("http://192.168.127.43:5000/send2", [selectedLocation, total, info])
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
};
function calculateTotal() {
console.log(info.cost * value);
var totalCost = info.cost * value;
setTotal(totalCost);
alert("Your reservation done \n Your service costs: " + total);
}
return (
<View>
<>
<View>
<Card
title={info.name}
caption={info.cost + " JD /H"}
>
<View
>
<Text>{info.place}</Text>
</View>
</Card>
<View>
<View>
<Text style={styles.text}>
Enter how many hours you need our service
</Text>
<TextInput
style={styles.input}
onChangeText={(text) => onChangeText(text)}
value={value}
></TextInput>
</View>
<View>
<Button
mode="contained"
onPress={calculateTotal}
>
<Text>Calculate total</Text>
</Button>
</View>
</View>
<View>
<View>
<Button
mode="contained"
onPress={onSubmit}
>
<Text>Done</Text>
</Button>
</View>
<View>
<Button
title="Submit"
mode="contained"
>
<Text>Cancel</Text>
</Button>
</View>
</View>
</View>
</>
</View>
);
}
// export default Confirm;
Nothing looks wrong in your code but for safer side wrap try and catch inside useEffect.
useEffect(()=>{
try {
//Retrieving user token, reserved nanny information and user location value from AsyncStorage
AsyncStorage.multiGet(["token", "nany", "location"]).then((res) => {
var nany = JSON.parse(res[1][1]);
var location = JSON.parse(res[2][1]);
setInfo(nany);
console.log("hi3");
setSelectedLocation(location);
});
} catch (error) {
throw error;
}
,[]);

how to do i map through this object in React Native?

it tried using like this
{ options.map( opt => {
return <Text>{opt.value}</Text>
}) }
Here iam taking the data from the backend and iam passing in to the DetailScreen.
class Poll extends Component {
state = {
loading:true,
pollDetails : []
}
componentDidMount(){
fetch('http://192.168.43.22:5000/api/v1/questions/5f1c31e1089847468cb9c508')
.then((response) => response.json())
.then((responseJson) => this.setState({pollDetails:responseJson.data}));
this.setState({loading:false});
}
render() {
const {loading, pollDetails} = this.state;
if(loading){
<View>
<Text><ActivityIndicator/></Text>
</View>
}
return(
<ScrollView>
<DetailsScreen
key={pollDetails._id}
title={pollDetails.title}
options={pollDetails.options}
voteCount={pollDetails.voteCount}
opinionCount={pollDetails.opinionCount}
loaded={true}
votes={60}
/>
</ScrollView>);
}
}
In Here i try to map through the options but it throws the error!
import React, {Component} from 'react';
import {View, Text, StyleSheet, Animated, TouchableOpacity} from 'react-native';
import Card from '../UI/Card';
export default class DetailScreen extends Component{
state = {
width:0,
voteCount: this.props.voteCount
}
handleOnLayout = ( {nativeEvent} ) => {
this.setState({width:nativeEvent.layout.width})
}
handleVotes = (id) => {
console.log(this.state.voteCount)
}
render(){
const {title, voteCount, votes, opinionCount, loaded} = this.props;
const _animatedWidth = new Animated.Value(0);
const animatedAnswerValue = () => {
const percentage = votes / voteCount;
const rowWidth = Math.floor(this.state.width * percentage);
Animated.timing(_animatedWidth,{
toValue:rowWidth,
duration:1500
}).start();
}
animatedAnswerValue();
const getOverlayStyles = (votes) => {
const s = [styles.optionBar];
if(votes > 50){
s.push(styles.optionBarHigh);
}
if(votes < 50 && votes > 20){
s.push(styles.optionBarMedium);
}
if(votes <= 20){
s.push(styles.optionBarLow)
}
return s;
}
return(
<View style={{marginLeft:100}}>
<Text style={{marginTop:50}}>{title}</Text>
{
this.props.options.map((opt,index) => {
return <Text key={index}>{opt.votes}</Text>
})
}
<Text>Just some sample text here!!!</Text>
{/* <TouchableOpacity key={options._id[0]} onPress={() => this.handleVotes(options._id)}>
<Card>
<Text>{options.value}</Text>
<View style={styles.optionBarRow} onLayout={this.handleOnLayout}>
<Animated.View
style={[getOverlayStyles(this.props.votes,loaded), {width:_animatedWidth}]}/>
<View style={styles.opinions}>
<Text style={{textAlign:"center"}}>Opinions</Text>
</View>
</View>
</Card>
</TouchableOpacity> */}
</View>
);
}
}
but it throw error of "Cannot read property 'map' of undefined
ive been scratching my head lately..
i'll be glad if some one sort this out for me!
thanks in advance :)
It might that data haven't been loaded on the very first render.
You can try to add an extra check for option to be in place, like:
{ options && options.map( opt => {
return <Text>{opt.value}</Text>
}) }

Conditional rendering with React Hooks : loading

I am learning how to use React Hooks and have been stuck for many hours on something that's supposed to be very simple.
I am trying to display a a text if the state variable "loading" is true. If it's false, I want to display something else.
No matter what I try, "loading" is always false or at least, the UI does not appear to reflect its value.
here is the code:
import React, {useState, useEffect} from 'react';
import {View, SafeAreaView, Text} from 'react-native';
const testScreen= (props) => {
const [loading, setLoading ] = useState(true);
useEffect(() => {
setLoading(false);
}, []);
if(loading)
{
return <Text>Hi</Text>;
}
else
{
return<Text.Hey</Text>
}
}
export default testScreen;
Any help will be more than welcome and I am sorry if this is very basic.
UPDATE: Here is the actual code I am working with. SetLoading is supposed to update the state variable to false but never does or at least, the UI des not render.
import React, {useState, useEffect} from 'react';
import {View, SafeAreaView, Text, ActivityIndicator} from 'react-native';
import CategoryTag from '../Components/CategoryTag';
import firestore from '#react-native-firebase/firestore';
const CategoryScreen = (props) => {
const topicCollection = firestore().collection('Topics')
.where("active","==",true);
//hooks for topics
const [topics,setTopics] = useState([]);
const [loading, setLoading ] = useState(true);
//get all active topics
useEffect(() => {
return topicCollection.onSnapshot(querySnapshot => {
const list = [];
querySnapshot.forEach(doc => {
const { active, name } = doc.data();
list.push({
id: doc.id,
active,
name,
});
});
setTopics(list);
setLoading(false);
});
}, []);
const renderTopics = () =>{
return(
topics.map((item) =>{
return(
<CategoryTag key = {item.id}
color={userTopics.includes(item.name) ?"#51c0cc":"#303239"}
name = {item.name}
isSelected = {userTopics.includes(item.name)}
handleClick = {addTopicToUserTopicCollection}
/>
)
})
)
}
if(loading)
{
return (
<SafeAreaView style={{flex:1, backgroundColor:"#455a65"}}>
<View style={{width:200, padding:20, paddingTop:60}}>
<Text style ={{fontSize:25, fontWeight:"bold",
color:"#fff"}}>What are you</Text>
<Text style ={{fontSize:22, color:"#fff"}}>interested in?
</Text>
</View>
<View style={{flex:1, alignItems:"center",
justifyContent:"center", alignSelf:"center"}}>
<ActivityIndicator />
</View>
</SafeAreaView>
)
}
else // this never runs
{
return (
<SafeAreaView style={{flex:1, backgroundColor:"#455a65"}}>
<View>
<View style={{width:200, padding:20, paddingTop:60}}>
<Text style ={{fontSize:25, fontWeight:"bold",
color:"#fff"}}>What are you</Text>
<Text style ={{fontSize:22, color:"#fff"}}>interested in?
</Text>
</View>
<View style ={{flexDirection:"column", paddingTop:20}}>
<View style ={{padding:15, paddingTop:15,
marginBottom:15,
flexWrap:"wrap", flexDirection:"row"}}>
{renderTopics(topics)}
</View>
</View>
</View>
</SafeAreaView>
);
}
}
export default CategoryScreen;
You are immediately setting your setLoading state to false and therefore loading text might be rendering for fraction of second, or not at all, like a glitch. Try setting setLoading with a timeout and then you will see the intended behaviour.
const TestScreen= (props) => {
const [loading, setLoading ] = useState(true);
useEffect(() => {
setTimeout(()=>setLoading(false), 3000);
}, []);
if(loading)
{
return <Text>Hi</Text>;
}
else
{
return<Text>hey</Text>
}
}

Categories