OPTION 2 - USING REDUX (RECOMMENDED)
I think this is the preferred option as Redux is industry standard and the data flow is simpler. Be aware that this is not a fully functioning example. I haven’t included setup for the Redux store, reducers or actions as that would confuse the point of this post.
-
TaskManager
fires its callback, passing its data tostore.dispatch(setLocation({latitude, longitude}))
- The connected
App
component receives the updates - The
_App
component is passed the updated props and the component re-renders
import * as Location from 'expo-location'
import * as Permissions from 'expo-permissions'
import * as TaskManager from 'expo-task-manager'
import React from 'react'
import { Text, View } from 'react-native'
import { store } from './redux/store'
import { connect } from 'react-redux'
const LOCATION_TASK_NAME = 'background-location-task'
const _App = ({ latitude, longitude }) => {
const trackUserLocation = async () => {
const { status } = await Permissions.askAsync(
Permissions.LOCATION,
Permissions.USER_FACING_NOTIFICATIONS
)
if (status === 'granted') {
await Location.startLocationUpdatesAsync(
LOCATION_TASK_NAME,
{
accuracy: Location.Accuracy.Highest,
distanceInterval: 1,
timeInterval: 5000
}
)
}
}
useEffect(() => {
trackUserLocation() // start tracking
}, [])
useEffect(() => {
return trackUserLocation() // cleanup
}, [])
return (
<View>
<Text>Lat: {latitude}</Text>
<Text>Lng: {longitude}</Text>
</View>
)
}
const mapState = ({ latitude, longitude }) => ({ latitude, longitude })
export default App = connect(mapState)(_App)
TaskManager.defineTask(LOCATION_TASK_NAME, ({ data, error }) => {
if (error) {
console.error(error)
return
}
if (data) {
const { latitude, longitude } = data.locations[0].coords
store.dispatch(setLocation({ latitude, longitude }))
}
})