问题
Is there a way to avoid update a callback in useEffect?. For example I am subscribed an event with geofire, this listens for changes and receive locations.
I need to update my state without subscribing every time on every update.
Current behavior
- Subscribed to geofire and receive location (A)
- Update my state with the new location (A)
- Subscribed to geofire again and receive location (A)
this is an infinite loop. And I can't receive the other locations
Expected behavior
- subscribed to geofire only once and receive locations (A,B,C)
- update my state with the new locations (A,B,C)
import React, {useState, useEffect} from 'react';
import {View, Text} from 'react-native';
import {GeoPosition, GeoError} from 'react-native-geolocation-service';
import {getCurrentLocation, LocationInfo} from '../../util/geolocation';
import GeoFireService, {EVENT_TYPE} from './services/GeoFireService';
interface CurrentLocation {
[key: string]: {
location: [number, number];
distance: number;
};
}
const Ads = () => {
const [locationInfo, setLocationInfo] = useState({
latitude: 0,
longitude: 0,
altitude: 0,
accuracy: 0,
} as LocationInfo);
const [currentLocation, setCurrentLocation] = useState({});
// set the current location
useEffect(() => {
getCurrentLocation(
(position: GeoPosition) => {
const {latitude, longitude, accuracy, altitude} = position.coords;
setLocationInfo({latitude, longitude, accuracy, altitude});
},
(err: GeoError) => {
console.log(err);
},
);
}, []);
// get ads
useEffect(() => {
(async () => {
if (locationInfo.latitude === 0 && locationInfo.longitude === 0) {
return null;
}
// this must be execute only once
await GeoFireService.queryToRadius(
[-34.5742746, -58.4744191],
30,
(key: string, location: [number, number], distance: number,) => {
// update state
setCurrentLocation({
...currentLocation,
[key]: {location},
});
},
);
})();
}, [locationInfo, currentLocation]);
// [locationInfo] with this option the update does not work
return (
<View>
<Text>
Latitude: {locationInfo.latitude} Longitude: {locationInfo.longitude}
</Text>
{Object.keys(currentLocation).map((key: string) => (
<Text key={key}>Ubicacion: {currentLocation[key].location}</Text>
))}
</View>
);
};
export default Ads;
回答1:
Have you checked if the return conditional is working on page load (just put a console log in there)?
From reading it, it seems both useEffects get called on page load, but the second one should exit immediately, and then get called again after the first one completes.
Then I notice you update state through an async call back, which may have something to do with it. It's difficult to say without seeing it in action.
I would say try rewriting your setCurrentLocation with a function rather than object:
setCurrentLocation((currentLocation) => ({
...currentLocation,
[key]: {location},
}));
Maybe its not getting passed through and toggling between new and old data.
来源:https://stackoverflow.com/questions/62629902/react-useeffect-avoid-update-callback-in-every-update