googlemaps / react-native-navigation-sdk

Apache License 2.0
17 stars 3 forks source link

MapViewCallbacks keep old references for variables #235

Closed nexttrack07 closed 2 weeks ago

nexttrack07 commented 3 weeks ago

SDK Version: 0.4.3

The MapViewCallbacks are not getting recreated when a state value changes. If I define local state variable and I use that variable inside a callback then the callback always has the initial value of the variable even if the variable gets updated. This happens even when the mapViewCallback is defined using useCallback and the the variable is listed as a dependency.

  const [appointmentMarkers, setAppointmentMarkers] = useState<Array<Marker>>(
    []
  );

const addMarkersToMap = useCallback(() => {
    mapViewController
      ?.isMyLocationEnabled()
      .then(() => {
        console.log('My Location Enabled');
      })
      .catch((e: any) => {
        console.log('My Location Disabled', e);
      });
    const addMarkerCalls = LatLngs.map(latLng => {
      return mapViewController?.addMarker({
        position: latLng,
        visible: true,
      });
    });

    Promise.all(addMarkerCalls).then(markers => {
      console.log('All markers added');
      navigationController.setDestinations(
        LatLngs.map(data => ({ position: data }))
      );

      const nonEmptyMarkers = markers.filter(Boolean) as Marker[];

      setAppointmentMarkers(nonEmptyMarkers);
    });
  }, [mapViewController, navigationController]);

  const onNavigationReady = useCallback(() => {
    console.log('onNavigationReady');

    addMarkersToMap();
  }, [addMarkersToMap]);

  console.log('Markers array (outside callback): ', appointmentMarkers);

const mapViewCallbacks: MapViewCallbacks = {
    onMapReady,
    onMarkerClick: useCallback(
      (marker: Marker) => {
        console.log(
          'onMarkerClick:',
          marker.id,
          appointmentMarkers.map(m => m.id)
        );
        const selectedMarker = appointmentMarkers.find(m => m.id === marker.id);

        console.log('Selected Marker:', selectedMarker);
      },
      [appointmentMarkers]
    ),
    onPolygonClick: (polygon: Polygon) => {
      console.log('onPolygonClick:', polygon);
      mapViewController?.removePolygon(polygon.id);
    },
    onCircleClick: (circle: Circle) => {
      console.log('onCircleClick:', circle);
      mapViewController?.removeCircle(circle.id);
    },
    onPolylineClick: (polyline: Polyline) => {
      console.log('onPolylineClick:', polyline);
      mapViewController?.removePolyline(polyline.id);
    },
    onMarkerInfoWindowTapped: (marker: Marker) => {
      console.log('onMarkerInfoWindowTapped:', marker);
    },
    onMapClick: (latLng: LatLng) => {
      console.log('onMapClick:', latLng);
    },
  };

You can see that there is a console.log with appointmentMarkers inside onMarkerClick and there is one outside. The outside one has the correct value of the appointmentMarkers and is updated. The one inside the onMarkerClick callback always has value [] and never gets updated. This same code existed in version 0.3.4 and worked perfectly.

Screenshot 2024-08-23 at 12 37 31 PM

I've tried putting onMarkerClick in a useCallback, defined it outside then referenced, I've removed the useMemo from mapViewCallbacks and it doesn't make any difference. The value of the state var inside any of mapViewCallbacks always stays the same and never updates.

jokerttu commented 2 weeks ago

Hi @nexttrack07 Please check PR #239, and let me know if it resolves this issue.

nexttrack07 commented 2 weeks ago

Thanks! Will check but doesn't look like the changes are release in a new version yet. Will it be released in 0.4.4?

jokerttu commented 1 week ago

@nexttrack07 Version 0.5.0 will be released soon Note that callbacks are still given as mapViewCallbacks prop. To detect changes, the mapViewCallbacks object need to be updated (as it is demonstrated in the SampleApp).