Stack Overflow Asked by VINEET SHARMA on July 28, 2020
I am a newbie in JavaScript and presently working with async/await in React Native. I have two async functions getAsyncLocation
and getParking
. getAsyncLocation
gets location from device as well from route params (obtained when routed from another screen). getParking
uses the state – mapRegion
– assigned by getAsyncLocation
to find relevant results.
However when I run them one after the other I am getting:-
[Unhandled promise rejection: TypeError: null is not an object (evaluating 'mapRegion.latitude')]
I have following code:-
const [mapRegion, setmapRegion] = useState(null);
handleMapRegionChange = (mapRegion) => setmapRegion({ mapRegion });
const handleCenterChange = (lat, lng) => setmapRegion({
latitude: lat,
longitude: lng,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
})
async function getAsyncLocation() {
if (route.params) { // obtained from some other screen
handleCenterChange(route.params.lat, route.params.lng);
console.log("route params for location ", mapRegion.latitude, mapRegion.longitude);
}
else {
const { status, permissions } = await Permissions.askAsync(
Permissions.LOCATION
);
if (status === "granted") {
sethasLocationPermission(true);
let location = await Location.getCurrentPositionAsync({});
setlocationResult(JSON.stringify(location));
handleCenterChange(location.coords.latitude, location.coords.longitude);
} else {
alert("Location permission denied");
}
}
}
async function getParkings() {
console.log("get parking runing")
console.log("get parkig ", mapRegion.latitude, ", ", mapRegion.longitude);
await axios.get(`http://${MyIp}:8080/booking/findParking`, {
params: {
lat: mapRegion.latitude,
lng: mapRegion.longitude,
rad: 10
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
.then((response) => {
let parkingSpace = response.data;
let parking = []
for (let i = 0; i < parkingSpace.length; i++) {
parking.push({
spaceId: parkingSpace[i]._id,
ownerId: parkingSpace[i].owner,
location:
{ latitude: parkingSpace[i].latitude, longitude: parkingSpace[i].longitude }
})
}
console.log(parking)
setSpace(parking);
})
.catch((err) => {
console.log(err)
})
}
async function getData() {
await getAsyncLocation();
await getParkings();
}
useEffect(() => {
getData();
}, []);
I have tried to search it in various blogs and stackoverflow question but could not get a way around. Would appreciate any hint.
Ciao, in order to execute getAsyncLocation
before getParkings
you have to use Promise. But there is another problem: even if you run sequentially getAsyncLocation
and getParkings
, is not guaranteed that in getParkings
mapRegion
has the value setted by getAsyncLocation
(because Hooks are async!). So how can solve your problem? You have several options. One is use 2 useEffect like this:
useEffect(() => {
getAsyncLocation();
}, []);
useEffect(() => {
getParkings();
}, [mapRegion]);
This approach has 2 problems:
useEffect
s live, first useEffect will be triggered (and maybe you don't want that).mapRegion
changes his value, second useEffect
will be triggered (and maybe you don't want that).So, I suggest a Promise approach as I said but passing value that getParkings
needs as a result of getAsyncLocation
. Your code becomes:
getAsyncLocation
async function getAsyncLocation() {
return new Promise(resolve => {
let result = {lat: -1, lng: -1};
if (route.params) { // obtained from some other screen
handleCenterChange(route.params.lat, route.params.lng);
console.log("route params for location ", mapRegion.latitude, mapRegion.longitude);
result.lat = route.params.lat;
result.lng = route.params.lng;
resolve(result);
return;
}
else {
const { status, permissions } = await Permissions.askAsync(
Permissions.LOCATION
);
if (status === "granted") {
sethasLocationPermission(true);
let location = await Location.getCurrentPositionAsync({});
setlocationResult(JSON.stringify(location));
handleCenterChange(location.coords.latitude, location.coords.longitude);
result.lat = location.coords.latitude;
result.lng = location.coords.longitude;
resolve(result);
return;
} else {
alert("Location permission denied");
}
}
resolve(result);
});
}
getParkings
async function getParkings(myMapRegion) {
return new Promise(resolve => {
console.log("get parking runing")
console.log("get parkig ", myMapRegion.lat, ", ", myMapRegion.lng);
await axios.get(`http://${MyIp}:8080/booking/findParking`, {
params: {
lat: myMapRegion.lat,
lng: myMapRegion.lng,
rad: 10
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
.then((response) => {
let parkingSpace = response.data;
let parking = []
for (let i = 0; i < parkingSpace.length; i++) {
parking.push({
spaceId: parkingSpace[i]._id,
ownerId: parkingSpace[i].owner,
location:
{ latitude: parkingSpace[i].latitude, longitude: parkingSpace[i].longitude }
})
}
console.log(parking)
setSpace(parking);
})
.catch((err) => {
console.log(err)
})
resolve();
});
}
getData
async function getData() {
let myMapRegion = await getAsyncLocation();
await getParkings(myMapRegion);
}
Answered by Giovanni Esposito on July 28, 2020
you can use another useEffect hook watching if the mapRegion state has been changed. (you can have as many useEffect hooks as you want in your app)
useEffect(() => {
getAsyncLocation();
}, []); // [] without any args, this will be called only once. We want to get device location only once
useEffect(() => {
getParkings();
}, [mapRegion]) // since we have passed mapRegion as arg therefore it would be called whenever mapRegion is updated
Answered by Tarukami on July 28, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP