React Native Maps not showing Markers on Android, even though API data is fetched correctly

I'm building a React Native app to display location markers on a map using react-native-maps. I'm using the Google Maps provider on Android. My problem is that the map loads, but the markers are not visible, even though I can confirm that my API call is successful and returns a valid array of location data.

MapsScreen.jsx:-

import React, { useState, useEffect, useRef, useMemo } from "react";
import {
  View,
  Text,
  StyleSheet,
  ActivityIndicator,
  Alert,
  SafeAreaView,
  TouchableOpacity,
  StatusBar,
  Modal,
} from "react-native";
import MapView, { Marker, Callout, PROVIDER_GOOGLE } from "react-native-maps";
import { useRoute, useNavigation } from "@react-navigation/native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { fetchMaps } from "../services/maps";

const StatusIndicator = ({ text }) => (
  <SafeAreaView style={styles.statusContainer}>
    <StatusBar barStyle="light-content" backgroundColor="#181d23" />
    <ActivityIndicator size="large" color="#27F0C9" />
    <Text style={styles.statusText}>{text}</Text>
  </SafeAreaView>
);

const isValidCoord = (lat, lng) =>
  Number.isFinite(lat) &&
  Number.isFinite(lng) &&
  Math.abs(lat) <= 90 &&
  Math.abs(lng) <= 180;

const MapsAnalysis = () => {
  const [points, setPoints] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  const [showInfo, setShowInfo] = useState(false);
  const [mapReady, setMapReady] = useState(false);

  const route = useRoute();
  const navigation = useNavigation();
  const { userId } = route.params;
  const mapRef = useRef(null);

  useEffect(() => {
    const getLocations = async () => {
      if (!userId) {
        setError("User ID not found. Cannot fetch map data.");
        setIsLoading(false);
        return;
      }
      try {
        setIsLoading(true);
        setError(null);

        const data = await fetchMaps(userId);
        const formattedData = Array.isArray(data)
          ? data
              .map((point) => {
                const lat = Number(point.latitude);
                const lng = Number(point.longitude);
                return {
                  ...point,
                  latitude: Number.isFinite(lat) ? lat : NaN,
                  longitude: Number.isFinite(lng) ? lng : NaN,
                  
                  pleasantness:
                    point.pleasantness != null ? Number(point.pleasantness) : null,
                  eventfulness:
                    point.eventfulness != null ? Number(point.eventfulness) : null,
                  annoyance:
                    point.annoyance != null ? Number(point.annoyance) : null,
                };
              })
              .filter((p) => isValidCoord(p.latitude, p.longitude))
          : [];

        console.log("Points to plot:", formattedData.length, formattedData.slice(0, 3));
        setPoints(formattedData);
      } catch (err) {
        console.error("Failed to fetch map data:", err);
        setError(err.message || "Could not load map data.");
        Alert.alert("Error", err.message || "Could not load map data.");
      } finally {
        setIsLoading(false);
      }
    };
    getLocations();
  }, [userId]);

  const coords = useMemo(
    () => points.map((p) => ({ latitude: p.latitude, longitude: p.longitude })),
    [points]
  );

  useEffect(() => {
    if (!mapReady || !mapRef.current || coords.length === 0) return;

    if (coords.length === 1) {
      
      const p = coords[0];
      mapRef.current.animateToRegion(
        {
          latitude: p.latitude,
          longitude: p.longitude,
          latitudeDelta: 0.02,
          longitudeDelta: 0.02,
        },
        600
      );
    } else {
      
      mapRef.current.fitToCoordinates(coords, {
        edgePadding: { top: 100, right: 100, bottom: 100, left: 100 },
        animated: true,
      });
    }
  }, [mapReady, coords]);

  if (isLoading) {
    return <StatusIndicator text="Loading Map Data..." />;
  }

  if (error) {
    return <StatusIndicator text={error} />;
  }

  if (points.length === 0) {
    return <StatusIndicator text="No map points found for this user." />;
  }

  return (
    <SafeAreaView style={styles.container}>
      <StatusBar barStyle="light-content" backgroundColor="#181d23" />

      <View style={styles.header}>
        <TouchableOpacity onPress={() => navigation.goBack()} style={{ padding: 5 }}>
          <Icon name="chevron-left" size={28} color="#fff" />
        </TouchableOpacity>
        <Text style={styles.headerTitle}>Analysis Map</Text>
        <TouchableOpacity onPress={() => setShowInfo(true)} style={{ padding: 5 }}>
          <Icon name="help-circle-outline" size={24} color="#fff" />
        </TouchableOpacity>
      </View>

      <Modal transparent visible={showInfo} animationType="fade">
        <View style={styles.overlay}>
          <View style={styles.infoModalBox}>
            <Text style={styles.infoTitle}>About The Map</Text>
            <Text style={styles.infoText}>
              This map shows the locations of all saved sound analyses. Tap on any pin to see the details of that specific analysis.
            </Text>
            <TouchableOpacity style={styles.closeBtn} onPress={() => setShowInfo(false)}>
              <Text style={styles.closeText}>Got It</Text>
            </TouchableOpacity>
          </View>
        </View>
      </Modal>

      <MapView
        ref={mapRef}
        provider={PROVIDER_GOOGLE}
        style={styles.map}
        // Delhi
        initialRegion={{
          latitude: 28.6139,
          longitude: 77.209,
          latitudeDelta: 0.5,
          longitudeDelta: 0.5,
        }}
        onMapReady={() => setMapReady(true)}
        onLayout={() => setMapReady(true)}
      >
        {points.map((point, index) => (
          <Marker
            key={`${point.id ?? index}`}
            coordinate={{ latitude: point.latitude, longitude: point.longitude }}
            
          >
            <Callout>
              <View style={styles.calloutView}>
                <Text style={styles.calloutTitle}>Analysis Details</Text>
                <Text>
                  Pleasantness:{" "}
                  {typeof point.pleasantness === "number"
                    ? point.pleasantness.toFixed(2)
                    : "N/A"}
                </Text>
                <Text>
                  Eventfulness:{" "}
                  {typeof point.eventfulness === "number"
                    ? point.eventfulness.toFixed(2)
                    : "N/A"}
                </Text>
                <Text>
                  Annoyance:{" "}
                  {typeof point.annoyance === "number"
                    ? point.annoyance.toFixed(2)
                    : "N/A"}
                </Text>
              </View>
            </Callout>
          </Marker>
        ))}
      </MapView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#181d23",
  },
  map: {
    flex: 1,
  },
  header: {
    width: "100%",
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    paddingVertical: 14,
    paddingHorizontal: 10,
    paddingTop: 30,
    backgroundColor: "#181d23",
  },
  headerTitle: {
    fontSize: 20,
    color: "#fff",
    fontWeight: "bold",
  },
  statusContainer: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: "#181d23",
  },
  statusText: {
    marginTop: 20,
    fontSize: 16,
    color: "#B6BAC5",
  },
  calloutView: {
    padding: 10,
    width: 200,
  },
  calloutTitle: {
    fontWeight: "bold",
    fontSize: 16,
    marginBottom: 5,
  },
  overlay: {
    flex: 1,
    backgroundColor: "rgba(0,0,0,0.7)",
    justifyContent: "center",
    alignItems: "center",
  },
  infoModalBox: {
    backgroundColor: "#2D2E32",
    padding: 25,
    borderRadius: 15,
    width: "85%",
    borderWidth: 1,
    borderColor: "rgba(255, 255, 255, 0.1)",
  },
  infoTitle: {
    color: "#FFFFFF",
    fontSize: 18,
    fontWeight: "bold",
    textAlign: "center",
    marginBottom: 15,
  },
  infoText: {
    color: "#E0E0E0",
    fontSize: 15,
    lineHeight: 22,
    marginBottom: 25,
  },
  closeBtn: {
    backgroundColor: "#27F0C9",
    paddingVertical: 12,
    paddingHorizontal: 30,
    alignSelf: "center",
    borderRadius: 8,
  },
  closeText: {
    color: "#181d23",
    fontWeight: "bold",
    fontSize: 16,
  },
});

export default MapsAnalysis;

Here is the debugger of react native

Maps On Emulator Maps On Emulator Maps On Emulator

DRF Terminal (Getting Latitude and Longitude from DB successfully)

Вернуться на верх