I am working on a React Native project created with Expo. I have created two callbacks that get specific data from the Expo Location API and sets the data into the state. Each callback is in an interval that is defined in the useEffect() hook of the app, and they both run at separate time intervals. One runs 2 times every second, whereas the other one runs 4 times a minute. If I just run the program with the first callback in the useEffect hook, it runs perfectly fine, but when I run both intervals in the useEffect hook, the second one for some reason temporarily resets the state before the first callback runs and resupplies the accurate data. If I console.log(state.speed) at the top of the second callback function, it is 0, which should not be correct because the first callback gives it the right speed. If anyone can figure out how to properly implement two callback functions running at separate intervals in the useEffect hook without the state being reset, then that will be great. Thanks!
import { StatusBar } from "expo-status-bar"; import { StyleSheet, Text, View, Image, SafeAreaView } from "react-native"; import { DateTime } from "luxon"; import { API_KEY, BASE_WEATHER_URL } from "../env"; import axios from "axios"; import * as Location from "expo-location";
const HUD = () => { const [state, setState] = useState({
speed: 0,
direction: "N/A",
speedUnits: "MPH",
heading: 0,
longitude: 0,
latitude: 0,
temperature: 0,
city: "",
region: "", });
const getGeolocation = useCallback(async () => {
try {
let location = await Location.getCurrentPositionAsync({
accuracy: Location.Accuracy.Highest,
});
const { speed, heading, longitude, latitude } = location.coords;
setState({
...state,
speed: Math.round(speed * 2.2369363),
direction: letterHeading(heading),
heading: Math.round(heading),
longitude,
latitude,
});
} catch (err) {
console.error(err);
} }, []);
const getArea = useCallback(async () => {
console.log(state.speed);
let area = await Location.reverseGeocodeAsync({
latitude: state.latitude,
longitude: state.longitude,
});
setState({ ...state, city: area[0].city, region: area[0].region }); }, []);
useEffect(async () => {
// Orientation.lockToLandscapeRight();
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
console.error("Permission to access location denied");
}
const locationInterval = setInterval(() => {
getGeolocation();
}, 500);
const areaInterval = setInterval(() => {
getArea();
}, 5000);
//The areaInterval, or getArea(), is the one that is resetting the state.speed
return () => {
clearInterval(locationInterval);
clearInterval(areaInterval);
};
}, [getGeolocation, getArea]);
return (
<SafeAreaView style={styles.container}>
<View style={styles.block}>
{/* <i class="fas fa-arrow-left" style={styles.backArrow} /> */}
<View style={{ flexDirection: "row" }}>
{/* <Text style={[styles.locationText, styles.mirrored]}>
{state.city}, {state.region}
</Text> */}
<Text style={[styles.temperature, styles.mirrored]}>
{state.temperature}° F
</Text>
<Text style={[styles.direction, styles.mirrored]}>
{letterHeading(state.heading)}
</Text>
</View>
</View>
<View style={[styles.block, { flexDirection: "row" }]}>
<Text style={[styles.timeText, styles.mirrored]}>{displayTime()}</Text>
<Text style={[styles.speedUnitText, styles.mirrored]}>
{state.speedUnits}
</Text>
<Text style={[styles.speedometer, styles.mirrored]}>{state.speed}</Text>
</View>
<View style={styles.block}>
<View style={{ flexDirection: "row" }}>
<Image
style={[styles.model, styles.mirrored]}
source={require("../assets/NIssan_Murano_Overhead_Photo.png")}
/>
</View>
</View>
<StatusBar style="black" />
</SafeAreaView>
);
};
Please note that some irrelevant parts of the above program have been removed so that way you can focus on the issue, which is the getArea() callback, since every time it runs my program display state.speed as 0 for some reason