0

ok so i have a page in react native that has a mapview and i am displaying the current location of the user and the destination of the user, at first the user's position on the map didn't move if the user moves, so i decided to use Location.watchPositionAsync, this worked perfectly, but noticed that the path in which the user was to take to reach the destination was not following the path of the road because i was using Polyline, so i change from that to MapViewDirections, but this also came with its own issue, everything is working but the MapViewDirections is always rerendering because the initial location is updating due to me using Location.watchPositionAsync, if the initial longitude and latitude are not changing the stuff works fine, but once its start changing it gives the issue,

does anyone have an idea on how to fix this? my code is below:

import {
 REACT_NATIVE_IMPORTS
} from "react-native";
import React, { REACT_IMPORTS } from "react";
import Modal from "react-native-modal";
import MapView, { Marker, Polyline } from "react-native-maps";
import { PROVIDER_GOOGLE } from "react-native-maps";
import Button from "../components/Button";
import { StatusBar } from "expo-status-bar";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import BottomSheet, { BottomSheetRefProps } from "../components/BottomSheet";
import P from "../components/P";
import H1 from "../components/H1";
import { Ionicons, AntDesign } from "@expo/vector-icons";
import MapViewDirections from "react-native-maps-directions";
import CustomMarker from "../components/CustomMarker";
import { Distance } from "../Request-Handlers/Functions";
import * as Location from "expo-location";
import CustomMarker2 from "../components/CustomMarker2";

const { width, height } = Dimensions.get("window");

function calculateTime(
  startLat: any,
  startLng: any,
  endLat: any,
  endLng: any,
  speed: any
) {
  const earthRadius = 6371; // Earth's radius in kilometers
  const distance = haversineDistance(
    startLat,
    startLng,
    endLat,
    endLng,
    earthRadius
  );
  const timeInSeconds = distance / speed;
  const timeInMinutes = Math.round(timeInSeconds / 60);

  return timeInMinutes;
}

function haversineDistance(
  lat1: any,
  lon1: any,
  lat2: any,
  lon2: any,
  radius: any
) {
  const toRadians = (value: any) => (value * Math.PI) / 180;

  const dLat = toRadians(lat2 - lat1);
  const dLon = toRadians(lon2 - lon1);

  const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(toRadians(lat1)) *
      Math.cos(toRadians(lat2)) *
      Math.sin(dLon / 2) *
      Math.sin(dLon / 2);

  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  const distance = radius * c;
  return distance;
}

export default function MapScreen({ route, navigation }: any) {
  const ref = useRef<BottomSheetRefProps>(null);
  const mapRef = useRef<MapView>(null);

  const { items } = route.params;

  const [isModalVisible, setModalVisible] = useState(false);
  const [lat, setLat] = useState(48.8587741);
  const [lon, setLon] = useState(2.2069771);
  const [distance, setDistance] = useState(0);

  const [locationFetched, setLocationFetched] = useState(false); // New state

  const onPress = useCallback(() => {
    const isActive = ref?.current?.isActive();
    if (isActive) {
      ref?.current?.scrollTo(0);
    } else {
      ref?.current?.scrollTo(-200);
    }
  }, []);

  const pickup = async () => {
    console.log(items.id);
    setModalVisible(false);
    navigation.navigate("ProffOfPickupScreen", { items: items });
  };


  const [location, setLocation] = useState({ latitude: 0, longitude: 0 });
  const [destination, setDestination] = useState({ latitude: 0, longitude: 0 });
  const [speed, setSpeed] = useState("");

  useEffect(() => {
    // Request permission to access the user's location
    const requestLocationPermission = async () => {
      const { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== "granted") {
        console.log("Permission to access location was denied");
        return;
      }

      // Start listening to location updates
      Location.watchPositionAsync(
        {
          accuracy: Location.Accuracy.High,
          timeInterval: 1000, // Update location every 1 second
          distanceInterval: 2, // Update location if the device moves 2 meters
        },
        (location) => {
          // @ts-ignore
          setLocation(location.coords);
          setLocationFetched(true);
          
          let distance = Distance(
            location.coords.latitude,
            location.coords.longitude,
            items.dropOffCoord.lat,
            items.dropOffCoord.lng
          );
          
          let time = calculateTime(
            location.coords.latitude,
            location.coords.longitude,
            items.dropOffCoord.lat,
            items.dropOffCoord.lng,
            0.011252
          );
          const hours = Math.floor(Number(time) / 60);
          const remainingMinutes = Number(time) % 60;

          setSpeed(`${hours}hr ${remainingMinutes}mins`);              
          setDistance(distance);
        }
        );
    };

    requestLocationPermission();
  }, []);

  useEffect(() => {
    // Set the destination coordinates
    setDestination({
      latitude: items.pickUpCoord.lat,
      longitude: items.pickUpCoord.lng,
    }); // Replace with your desired destination coordinates
  }, [location]);

  

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <StatusBar style="dark" />

      <View style={styles.container}>
        {locationFetched && (
          <MapView
            style={styles.map}
            provider={PROVIDER_GOOGLE}
            initialRegion={{
              // @ts-ignore
              latitude: location.latitude,
              // @ts-ignore
              longitude: location.longitude,
              latitudeDelta: 0.01,
              longitudeDelta: 0.01,
            }}>
            <MapViewDirections
              origin={{
                latitude: location.latitude,
                longitude: location.longitude,
              }}
              destination={{
                latitude: items.pickUpCoord.lat,
                longitude: items.pickUpCoord.lng,
              }}
              apikey="MY_API"
              strokeWidth={4}
              strokeColor="#111111"
            />
            <CustomMarker coordinate={location} />
            <CustomMarker2 coordinate={destination} distance={distance} />
            {/* <Polyline
              // @ts-ignore
              coordinates={[location, destination]}
              strokeWidth={4}
              strokeColor="black"
            /> */}
          </MapView>
        )}

        <TouchableOpacity
          style={{
            width: (10 * width) / 100,
            height: (10 * width) / 100,
            backgroundColor: "#F1F3F9",
            position: "absolute",
            borderRadius: 100,
            justifyContent: "center",
            alignItems: "center",
            top: "6%",
            left: "5%",
          }}
          onPress={() => navigation.pop()}>
          <AntDesign name="arrowleft" size={24} color="black" />
        </TouchableOpacity>

        <StatusBar style="light" />
        <TouchableOpacity style={styles.button} onPress={onPress} />
        <BottomSheet ref={ref}>
          <View
            style={{
              flex: 1,
              backgroundColor: "white",
            }}>
            <View
              style={{
                flexDirection: "row",
                alignItems: "center",
                paddingHorizontal: "5%",
              }}>
              <H1 style={{ marginRight: "2%" }}>{speed}</H1>
              {/* <H1 style={{ marginRight: "2%" }}>1hr 40mins</H1> */}
              <H1 style={{ marginRight: "2%", color: "gray" }}>
                {"("}
                {distance.toFixed(1)}km{")"}
              </H1>
            </View>
            <P style={{ fontSize: (3 * width) / 100, marginLeft: "5%" }}>
              You’re driving to the pickup address
            </P>
            <View
              style={{
                height: 1,
                width: "100%",
                backgroundColor: "#ddd",
                marginTop: "5%",
              }}></View>

            <View
              style={{
                width: "97%", 
                paddingLeft: "3%",
               
              }}>
              <View style={styles.cardinside}>
                <Ionicons name="location-sharp" size={20} color="gold" />
                <P style={styles.upLeft1}>Est. Pick Up:</P>
                <P style={styles.upRight}>{items.pickUpDate.split(" ")[1]}</P>
              </View>

              
              <View style={styles.cardinside1}>
                <Ionicons name="location-sharp" size={20} color="#00000000" />
                <P style={styles.downRight}>{items.dropoffLocation}</P>
              </View>
            </View>

            <Button
              Title="Mark as picked up"
              type="warning"
              full={true}
              onPress={() => pickup()}
              css={{ marginTop: "-1%" }}
            />
          </View>
        </BottomSheet>
      </View>
    </GestureHandlerRootView>
  );
}

const styles = StyleSheet.create({
 // MY_STYLES
});
Curtis Crentsil
  • 459
  • 6
  • 20

0 Answers0