Why expo background location stop sending location after 5 min? - react-native

I defined the task in App.js, everthing works fine! but after 5 min it stops sending the location, I dont know why.
I'm using this package: https://docs.expo.io/versions/latest/sdk/location/#background-location-methods
TaskManager.defineTask(LOCATION_TASK_NAME, async ({ data, error }) => {
console.log("Esta entrando al task")
if (error) {
console.log(error)
// Error occurred - check `error.message` for more details.
return;
}
if (data) {
const { locations } = data;
let getLastTime = await AsyncStorage.getItem('lastTime');
if(getLastTime){
let timeInterval = moment(new Date()).diff(getLastTime,'seconds')
if(timeInterval<=10) {
return
}
}
await LocationAPI.sendCurrentLocation(locations[0].coords).then(async res=>{
await AsyncStorage.setItem('lastTime', new Date().toString())
}).catch(err=>{
console.log(err)
console.log("en el task")
})
// do something with the locations captured in the background
}
});

Related

React Native UseEffect function is not working according to order

I want to get user's current location and set it into AsyncStorage a array. I will do it in the useEffect hook. But the problem is my functions are not working that according to given order. Here are my code
useEffect(() => {
getUserLocation();
setUserLocation();
check();
}, []);
/*Get User's Currunt Location*/
const getUserLocation = () => {
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then((location) => {
var lt = location.latitude;
var lg = location.longitude;
setlatitude(lt);
setlongitude(lg);
console.log("getUserLocation", lt, lg);
})
.catch((error) => {
const { code, message } = error;
console.warn(code, message);
});
};
/*Set User's Currunt Location to AsyncStorage*/
const setUserLocation = async () => {
try {
await AsyncStorage.setItem("user_location", JSON.stringify(userLocation));
console.log("setUserLocation", userLocation);
} catch (error) {
console.log("error setting user location");
}
};
const check = () => {
AsyncStorage.getItem("user_location", (err, result) => {
if (result !== null) {
console.log("check", result);
setlatitude(result.latitude);
setlongitude(result.longitude);
} else {
console.log("Data Not Found");
}
});
};
Whenever you use .then you are scheduling your code to run at some point in the future, when the promise has completed. So setUserLocation runs before the then of getUserLocation.
Also, it looks like your getUserLocation set react state, which won't be available until the next render. We use effects to manage this.
// Get the location on mount
useEffect(getUserLocation, []);
// Whenever the location updates, set it into storage
useEffect(() => setUserLocation().then(check), [latitude, longitude]);

React Hook does not set on first API call

So I am sure I am messing something up, but I am not super skilled at API.
So I am trying to make an API call to check if the user exists, if user exists then move about business, if not then do other stuff.
So my first call gets the data, and the user DOES exist, the hook is setting to true, however in my log it fails and the next API is ran. However if I do it a 2nd time, it is true...
What am I doing wrong.
const handleSubmit = async () => {
const data = await axios
.get(`URL`, {
})
.then((resp) => {
if (resp.data.user.name) {
setCheckUser(true);
console.log(resp.data.user.name);
}
return data;
})
.catch((err) => {
// Handle Error Here
console.error(err);
});
console.log(checkUser);
if (!checkUser) {
console.log('No User Found');
//Do Stuff//
}
};
I think the problem here is that setCheckUser(true) is an async operation, so there is no guarantee that the checkUser variable will turn to true right away.
Maybe you can solve this by using a useEffect block like this
//somewhere on the top of your file, below your useState statements
useEffect(()=> {
if (!checkUser) {
console.log('No User Found');
//Do Stuff//
}
}, [checkUser])
const handleSubmit = async () => {
const data = await axios
.get(`URL`, {
})
.then((resp) => {
if (resp.data.user.name) {
setCheckUser(true);
console.log(resp.data.user.name);
}
return data;
})
.catch((err) => {
// Handle Error Here
console.error(err);
});
};

Can't perform a React state update on an unmounted component. useEffect Hook

I seem to be missing something subtle about avoiding memory leaks. I have read a few posts on how to avoid this with async functions and have tried a few things. All seem to fail. Could someone point out what I'm doing wrong.
useEffect(() => {
let ignore = false;
if (Platform.OS === "android" && !Constants.isDevice) {
errorMessage("Oops, this will not work on Sketch in an Android emulator. Try it on your device!");
} else {
// function to get location, weather and aurora info
const getDataAsync = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
setErrorMessage("Permission to access location was denied");
}
if (!ignore) {
let location = await Location.getCurrentPositionAsync({});
// do stuff with the location data, putting it into states
fetch(`http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&APPID=${API_KEY}&units=metric`)
.then(res => res.json())
.then(json => {
// do all sorts of stuff with the weather json, putting it into states
});
// Fetch the aurora data
const myUTC = new Date().getTimezoneOffset();
fetch(`http://api.auroras.live/v1/?type=ace&data=bz&tz=${myUTC}&colour=hex`)
.then(res => res.json())
.then(json => {
// do stuff with the aurora json, put it into states
});
setIsLoaded(true); // this is for the activity indicator
}
}
getDataAsync();
return () => { ignore = true; }
}
}, []);
I'm getting the error when deliberately quickly switching out of the screen and back again while the activity indicator is spinning.
Return the cleanup outside of everything! let me know if it works
useEffect(() => {
let ignore = false;
if (Platform.OS === 'android' && !Constants.isDevice) {
errorMessage(
'Oops, this will not work on Sketch in an Android emulator. Try it on your device!',
);
} else {
// function to get location, weather and aurora info
const getDataAsync = async () => {
let {status} = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
setErrorMessage('Permission to access location was denied');
}
if (!ignore) {
let location = await Location.getCurrentPositionAsync({});
// do stuff with the location data, putting it into states
fetch(
`http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&APPID=${API_KEY}&units=metric`,
)
.then((res) => res.json())
.then((json) => {
// do all sorts of stuff with the weather json, putting it into states
});
// Fetch the aurora data
const myUTC = new Date().getTimezoneOffset();
fetch(
`http://api.auroras.live/v1/?type=ace&data=bz&tz=${myUTC}&colour=hex`,
)
.then((res) => res.json())
.then((json) => {
// do stuff with the aurora json, put it into states
});
setIsLoaded(true); // this is for the activity indicator
}
};
getDataAsync();
}
return () => {
ignore = true;
};
}, []);
That was promising, but no, it didn't work. It may have to do with the fact that there are 2 async fetch requests and one "await" location request with each taking a different amount of time.
I am trying with abortController but that isn't working either:
useEffect(() => {
const abortController = new AbortController();
if (Platform.OS === 'android' && !Constants.isDevice) {
errorMessage(
'Oops, this will not work on Sketch in an Android emulator. Try it on your device!',
);
} else {
// function to get location, weather and aurora info
const getDataAsync = async () => {
let {status} = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
setErrorMessage('Permission to access location was denied');
}
let location = await Location.getCurrentPositionAsync({signal: abortController.signal});
// do stuff with the location data, putting it into states
fetch(
`http://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${long}&APPID=${API_KEY}&units=metric`, { signal: abortController.signal })
.then((res) => res.json())
.then((json) => {
// do all sorts of stuff with the weather json, putting it into states
});
// Fetch the aurora data
const myUTC = new Date().getTimezoneOffset();
fetch(
`http://api.auroras.live/v1/?type=ace&data=bz&tz=${myUTC}&colour=hex`, { signal: abortController.signal })
.then((res) => res.json())
.then((json) => {
// do stuff with the aurora json, put it into states
});
setIsLoaded(true); // this is for the activity indicator
};
getDataAsync();
}
return () => {
abortController.abort();
}
}, []);
In addition to the memory leak error in the console, I am also getting:
Possible Unhandled Promise Rejection (id: 0):
[AbortError: Aborted]
Possible Unhandled Promise Rejection (id: 1):
[AbortError: Aborted]

React Native variable getting undefined before running method

I have a function that calls a method that is in my Helper.js file.
import { getTest } from '../../common/Helper';
...
myMethod() {
...
const test = getTest(this.state.myID);
console.log(test);
}
...
My Helper.js:
export const getTest = (pID) => {
axios.get('http://myserver.com/', {
params: {
method: 'getVacantUnits',
propertyID: pID
}
}).then((response) => {
console.log(response.data);
return response.data;
}).catch((error) => {
// handle error
console.log(error);
return 0;
});
};
It is odd because my output is:
undefined
myDataContent
It looks like that "const test" is receiving undefined before the getTest being run. Why is it happening?
Thanks
It's returning this first since it's not awaiting the result:
console.log(test);
2 easy ways to fix this I am showing below, first with promise:
const test = getTest(this.state.myID).then(response=> console.log(response)).catch(err => console.log(err))
Add in return as well since you need to return from outermost function
export const getTest = (pID) => {
return axios.get('http://myserver.com/', {
params: {
method: 'getVacantUnits',
propertyID: pID
}
}).then((response) => {
console.log(response.data);
return response.data;
}).catch((error) => {
// handle error
console.log(error);
return 0;
});
};
second using async await:
// add in await
export const getTest = async (pID) => {
return axios.get('http://myserver.com/', {
params: {
method: 'getVacantUnits',
propertyID: pID
}
}).then((response) => {
console.log(response.data);
return response.data;
}).catch((error) => {
// handle error
console.log(error);
return 0;
});
};
// here you are awaiting the response before you run console.log
const test = await getTest(this.state.myID);
console.log(test);
You can solve this in several other ways, but I think these are the 2 easiest. Basically think about the fact that those are run synchronously and the console.log executes before the function returns, so if you "wait" then it makes it so the console.log() is dependent on the first function executing first.

React native asyncstorage cannot get data

I'm starting my react-native project with npm start. On my emulator I have installed expo to view my application. Also I'm using http://ip:19001/debugger-ui/ to debug my application in google chrome.
I don't know what I'm doing wrong but I can't get any data from asyncstorage. Can you please give me some tips how to correct this problem.
In one of my activities I store data with;
storeDataInAsync1(idSchool,year) {
try {
//await AsyncStorage.removeItem('user');
AsyncStorage.setItem('dateRange', this.props.range);
AsyncStorage.setItem('idSchool', idSchool);
AsyncStorage.setItem('school_year', year);
} catch (error) {
// Error saving data
}
}
My call to this method;
async saveMyProfil() {
var formData = new FormData();
formData.append('id_school',this.props.idSchool);
formData.append('school_year', this.props.year);
await fetch(`${api.url}/my_profile/`, {
method: 'POST',
headers: {
"Content-Type": "multipart/form-data"
},
body: formData,
}).then((response) => response.json())
.then((json) => {
console.log('Response: ' + JSON.stringify(json));
this.storeDataInAsync1(json.id_school,json.school_year);
//_storeData(json.id_school,json.school_year);
//this.doStuff(json.id_school,json.school_year);
})
.catch((error) => {
});
}
back() {
//this.storeDataInAsync();
this.saveMyProfil();
this.props.navigation.goBack();
}
In another activity there is method to retrive data;
_retrieveData = async () => {
try {
const value = await AsyncStorage.getItem('idSchool');
const year = await AsyncStorage.getItem('school_year');
if (value !== null && year !== null) {
// We have data!!
console.log('Id School: ' + value);
console.log('Year: ' + year);
}
} catch (error) {
// Error retrieving data
}
}
I call _retrieveData in;
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
this._retrieveData();
}