React Native MapView - select marker by press on a list item

Viewed 416

Im trying to combine aside my markers in the mapView component, a list of markers that in pressing on each item it would automaticly select the marker on the map.

I already created a mapView, marker list, and created a ref for each marker. but I didn't succeed to handle the selection. In the documentation here I found the isPreselected prop but it's works only on IOS, and I search for solution also for android.

Here is my code:

import MapView, { Marker } from "react-native-maps";
import {
  StyleSheet,
  Text,
  View,
  Dimensions,
  FlatList,
  Button,
} from "react-native";
import { createRef, useRef } from "react";

export default function App() {
  const mapRegions = [
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -122.4324,
      },
    },
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -123.4324,
      },
    },
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -120.4324,
      },
    },
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -121.4324,
      },
    },
  ];
  const markerRef = useRef(mapRegions.map(() => createRef()));

  const selectLocation = (index) => {
    const ref = markerRef.current[index].current;
    console.log(ref);
  };
  return (
    <View style={styles.container}>
      <MapView style={styles.map}>
        {mapRegions.map((r, index) => (
          <Marker
            ref={markerRef.current[index]}
            coordinate={r.location}
            key={r.location.latitude}
            title="Marker"
          />
        ))}
      </MapView>
      <View>
        <FlatList
          data={mapRegions}
          keyExtractor={(region) => region.location.latitude.toString()}
          renderItem={({ item, index }) => (
            <View>
              <Text>{item.name}</Text>
              <Button
                title="see location"
                onPress={() => selectLocation(index)}
              />
            </View>
          )}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  map: {
    width: Dimensions.get("window").width,
    height: Dimensions.get("window").height,
  },
});
1 Answers

I Found The Solution. Instead to give an ref for each Marker, I only had to set a ref to the MapView Component, and use the animateToRegion() method that recieve the location, and the duration of the animation. I also had to define a latitudeDelta and longitudeDelta properties to the locations array.

This is the currect code:

import * as React from "react";
import MapView, { Marker } from "react-native-maps";
import {
  StyleSheet,
  Text,
  View,
  Dimensions,
  FlatList,
  Button,
} from "react-native";
import { useRef } from "react";

export default function App() {
  const mapRegions = [
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -122.4324,
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      },
    },
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -123.4324,
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      },
    },
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -120.4324,
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      },
    },
    {
      name: "place-one",
      location: {
        latitude: 41.78825,
        longitude: -121.4324,
        latitudeDelta: 0.01,
        longitudeDelta: 0.01,
      },
    },
  ];
  const mapRef = useRef(null);
  const selectLocation = (region) => {
    mapRef.current.animateToRegion(region, 1000);
  };
  return (
    <View style={styles.container}>
      <MapView ref={mapRef} style={styles.map}>
        {mapRegions.map((r, index) => (
          <Marker
            coordinate={r.location}
            key={r.location.longitude.toString()}
            title="Marker"
          />
        ))}
      </MapView>
      <View>
        <FlatList
          data={mapRegions}
          keyExtractor={(region) => region.location.longitude.toString()}
          renderItem={({ item, index }) => (
            <View>
              <Text>{item.name}</Text>
              <Button
                title="see location"
                onPress={() => selectLocation(item.location)}
              />
            </View>
          )}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  map: {
    width: Dimensions.get("window").width,
    height: Dimensions.get("window").height,
  },
});


Related