React useEffect 避免在每次更新时更新回调

React useEffect avoid update callback in every update

有没有办法避免在 useEffect 中更新回调?。例如,我用 geofire 订阅了一个事件,它监听变化并接收位置。

我需要更新我的状态,而不是每次更新都订阅。

当前行为

  1. 已订阅 geofire 并接收位置 (A)
  2. 使用新位置 (A) 更新我的状态
  3. 再次订阅 geofire 并接收位置 (A)

这是一个无限循环。我无法收到其他位置

预期行为

  1. 仅订阅一次 geofire 并接收位置 (A,B,C)
  2. 使用新位置(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;

您是否检查过 return 条件是否在页面加载时起作用(只需将控制台日志放在那里)?

从阅读来看,似乎两个 useEffects 都在页面加载时被调用,但第二个应该立即退出,然后在第一个完成后再次调用。

然后我注意到你通过异步回调更新状态,这可能与它有关。不亲眼所见很难说。

我会说尝试用函数而不是对象重写 setCurrentLocation:

setCurrentLocation((currentLocation) => ({
    ...currentLocation,
    [key]: {location},
}));

也许它没有通过并在新旧数据之间切换。