Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Map Displays Default Region Before User Location is Fetched #8

Open
olafswan opened this issue Sep 27, 2024 · 0 comments
Open

Comments

@olafswan
Copy link

olafswan commented Sep 27, 2024

Issue Description:

In the current implementation of the components/Map.tsx file, the map is being rendered with a default region (latitude: 37.78825, longitude: -122.4324) before the user's actual location is fetched.
This causes the map in homepage to display the default location (San Francisco) momentarily, and the map doesn't update automatically when the actual location is retrieved.

The issue arises because of the order of execution. At the first render, the coordinates (userLatitude, userLongitude) are null, so the default region is always used initially.
Additionally, Map.tsx is using initialRegion, which sets the region once at the initial render and doesn’t update when the coordinates from the state change.

Explanation of Execution Flow:

Initially, when the Map component renders, userLatitude and userLongitude are null, so the default region values (latitude: 37.78825, longitude: -122.4324) are used.
After the requestLocation function in Home.tsx retrieves the actual coordinates, it updates the Zustand store. At this point, the store has the correct values for userLatitude and userLongitude.
However, by this time, the map has already rendered with the initial (null) values and doesn't update automatically.

Suggested Fix:

To ensure that the map correctly displays the user's current location once it’s fetched, we can prevent the map from rendering until the location data is available. This avoids showing the default region and ensures the map uses the user's actual coordinates.

Updated Solution for Map.tsx:

I suggest updating the Map.tsx file to conditionally render the map only when userLatitude and userLongitude are available using this if statment:

 if (userLatitude === null || userLongitude === null) {
    return <Text>Loading Map...</Text>;
  }

Here’s the revised code for Map.tsx:

.components/Map.tsx
import React, { useEffect, useState } from "react";
import { ActivityIndicator, Text, View } from "react-native";
import MapView, { Marker, PROVIDER_DEFAULT } from "react-native-maps";
import MapViewDirections from "react-native-maps-directions";

import { icons } from "@/constants";
import { useFetch } from "@/lib/fetch";
import {
  calculateDriverTimes,
  calculateRegion,
  generateMarkersFromData,
} from "@/lib/map";
import { useDriverStore, useLocationStore } from "@/store";
import { Driver, MarkerData } from "@/types/type";

const directionsAPI = process.env.EXPO_PUBLIC_DIRECTIONS_API_KEY;

const Map = () => {
  const {
    userLongitude,
    userLatitude,
    destinationLatitude,
    destinationLongitude,
  } = useLocationStore();
  const { selectedDriver, setDrivers } = useDriverStore();

  const { data: drivers, loading, error } = useFetch<Driver[]>("/(api)/driver");
  const [markers, setMarkers] = useState<MarkerData[]>([]);

  useEffect(() => {
    if (Array.isArray(drivers)) {
      if (!userLatitude || !userLongitude) return;

      const newMarkers = generateMarkersFromData({
        data: drivers,
        userLatitude,
        userLongitude,
      });

      setMarkers(newMarkers);
    }
  }, [drivers, userLatitude, userLongitude]);

  useEffect(() => {
    if (
      markers.length > 0 &&
      destinationLatitude !== undefined &&
      destinationLongitude !== undefined
    ) {
      calculateDriverTimes({
        markers,
        userLatitude,
        userLongitude,
        destinationLatitude,
        destinationLongitude,
      }).then((drivers) => {
        setDrivers(drivers as MarkerData[]);
      });
    }
  }, [markers, destinationLatitude, destinationLongitude]);

  const region = calculateRegion({
    userLatitude,
    userLongitude,
    destinationLatitude,
    destinationLongitude,
  });

  if (loading || (!userLatitude && !userLongitude))
    return (
      <View className="flex justify-between items-center w-full">
        <ActivityIndicator size="small" color="#000" />
      </View>
    );

  if (error)
    return (
      <View className="flex justify-between items-center w-full">
        <Text>Error: {error}</Text>
      </View>
    );

  // Don't render the map until we have user location, show a loader or placeholder 
  if (userLatitude === null || userLongitude === null) {
    return <Text>Loading Map...</Text>;
  }

  return (
    <MapView
      provider={PROVIDER_DEFAULT}
      className="w-full h-full rounded-2xl"
      tintColor="black"
      mapType="mutedStandard"
      showsPointsOfInterest={false}
      initialRegion={region}
      showsUserLocation={true}
      userInterfaceStyle="light"
    >
      {markers.map((marker, index) => (
        <Marker
          key={marker.id}
          coordinate={{
            latitude: marker.latitude,
            longitude: marker.longitude,
          }}
          title={marker.title}
          image={
            selectedDriver === +marker.id ? icons.selectedMarker : icons.marker
          }
        />
      ))}

      {destinationLatitude && destinationLongitude && (
        <>
          <Marker
            key="destination"
            coordinate={{
              latitude: destinationLatitude,
              longitude: destinationLongitude,
            }}
            title="Destination"
            image={icons.pin}
          />
          <MapViewDirections
            origin={{
              latitude: userLatitude!,
              longitude: userLongitude!,
            }}
            destination={{
              latitude: destinationLatitude,
              longitude: destinationLongitude,
            }}
            apikey={directionsAPI!}
            strokeColor="#0286FF"
            strokeWidth={2}
          />
        </>
      )}
    </MapView>
  );
};

export default Map;

Explanation:

  1. Conditional Rendering: The MapView component is only rendered once the userLatitude and userLongitude are fetched, preventing the default region from being displayed prematurely.
  2. Improved User Experience: The map now waits for the correct coordinates and avoids showing incorrect information (e.g., default San Francisco coordinates) when the user’s actual location is still being retrieved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant