Dynamically Rendering MapView Marker React Native - javascript

This is how my Map View Looks like :
<MapView
style={styles.mapStyle}
initialRegion={{
latitude: 51.524300,
longitude: -0.037790,
latitudeDelta: 0.0122,
longitudeDelta: 0.0421,
}}
>
<Marker
coordinate={{
latitude:51.524464,
longitude:-0.036285,
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title={"Marker 1"}
description={customData.text1}
/>
<Marker
coordinate={{
latitude:51.524310,
longitude:-0.037798,
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title={"Marker 2"}
description={customData.text2}
/>
<Marker
coordinate={{
latitude:51.523174,
longitude:-0.039332,
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title={"Marker 3"}
description={customData.text3}
/>
</MapView>
As you can see I have hard-coded 3 markers just to make sure that the MapViews works properly. Now, I use an external API which tells the parking spaces based on the user's input. So for example if the user enter's a certain postcode/ ZIP code, the api returns an array where I have various information about the parking space such as longitude and latitude. I want to represent these parking spaces with markers on the map. I use a FlatList for that:
<FlatList
data = {parkingSpaces}
renderItem={({ item }) => {
return <MapView.Marker
coordinate={{
latitude: parseInt(item.latitude),
longitude:parseInt(item.longitude)
}}
title = {"parking markers"}
/>
}}
keyExtractor={item => item.unique_identifier}
/>
I don't get any errors, however I can't see the markers on the map. Below is my full code
import React ,{Component,useState,useEffect} from 'react'
import {View,Text,StyleSheet,Dimensions,Button,Alert,FlatList} from 'react-native'
import MapView , {Marker}from 'react-native-maps'
import axios from 'axios'
import { TextInput } from 'react-native-gesture-handler'
import camdenParking from '../api/camdenParking'
import SearchBar from '../components/SearchBar'
/// Key Secret : 5ulg30lagu2o493uwsmn24rxklsg0ivb05k2zl6xqhiz8js9e7
/// App Secret Token : NTEX14nQLbrS8MIz4RmC6riUV6K2aQ_j687H
const HomeScreen = ()=>
{
const [parkingSpaces,setparkingSpaces] = useState([])
const[term,setTerm] = useState('')
let userLatitude = 0
let userLongitude = 0
const customData = require("./MarkersText.json")
const searchApi = async() => {
const response = await camdenParking.get("",{
params:{
//longitude:-0.115444,
//latitude:51.517597
postcode: term
}
}) // you can change this later on
console.log(response.data)
setparkingSpaces(response.data)
console.log(term)
}
const findCoordinates = () => {
navigator.geolocation.getCurrentPosition(
position => {
const locationString = JSON.stringify(position); // Here we get the JSON object but it needs to be parsed
var longLat = JSON.parse(locationString); // Here we parse the JSON object
userLatitude=longLat.coords.latitude
userLongitude=longLat.coords.longitude
console.log(userLatitude) // This prints the current latitude from the user
console.log(userLongitude) // This prints the longitude
},
error => Alert.alert(error.message),
{ enableHighAccuracy: false, timeout: 20000, maximumAge: 1000 }
);
};
//useEffect(()=>{
// searchApi()
//},[])
return(
<View style={styles.container}>
<SearchBar
term={term}
onTermChange={newTerm=>setTerm(newTerm)}
onTermSubmit={()=> searchApi(term)}
/>
<MapView
style={styles.mapStyle}
initialRegion={{
latitude: 51.524300,
longitude: -0.037790,
latitudeDelta: 0.0122,
longitudeDelta: 0.0421,
}}
>
<Marker
coordinate={{
latitude:51.524464,
longitude:-0.036285,
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title={"Marker 1"}
description={customData.text1}
/>
<Marker
coordinate={{
latitude:51.524310,
longitude:-0.037798,
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title={"Marker 2"}
description={customData.text2}
/>
<Marker
coordinate={{
latitude:51.523174,
longitude:-0.039332,
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title={"Marker 3"}
description={customData.text3}
/>
</MapView>
<Text>We have found {parkingSpaces.length} results</Text>
<Button onPress={searchApi} title=" Click Here To Get Parking Spaces" />
<Button onPress={findCoordinates} title=" Click Here To Get User's Location" />
<Text>Parking Spaces found around {term}</Text>
<FlatList
data = {parkingSpaces}
renderItem={({ item }) => {
return <MapView.Marker
coordinate={{
latitude: parseInt(item.latitude),
longitude:parseInt(item.longitude)
}}
title = {"parking markers"}
/>
}}
keyExtractor={item => item.unique_identifier}
/>
<FlatList
data = {parkingSpaces}
renderItem={({ item }) => {
return <Text> {item.road_name} | Possible Available Spaces:{item.parking_spaces} </Text>
}}
keyExtractor={item => item.unique_identifier}
/>
</View>
);
};
const styles = StyleSheet.create(
{
container:{
flex:1,
backgroundColor: '#fff',
//alignItems: 'center',
//justifyContent: 'center',
//...StyleSheet.absoluteFillObject,
//marginLeft:0,
//height:400,
//width:400,
//justifyContent:"flex-end",
//alignItems:"center",
},
mapStyle: {
width: 400,
height:400,
//width: Dimensions.get('window').width,
//height: Dimensions.get('window').height,
},
}
)
export default HomeScreen
UPDATE
This is how my code looks like now:
import React ,{Component,useState,useEffect} from 'react'
import {View,Text,StyleSheet,Dimensions,Button,Alert,FlatList} from 'react-native'
import MapView , {Marker}from 'react-native-maps'
import axios from 'axios'
import { TextInput } from 'react-native-gesture-handler'
import camdenParking from '../api/camdenParking'
import SearchBar from '../components/SearchBar'
/// Key Secret : 5ulg30lagu2o493uwsmn24rxklsg0ivb05k2zl6xqhiz8js9e7
/// App Secret Token : NTEX14nQLbrS8MIz4RmC6riUV6K2aQ_j687H
const HomeScreen = ()=>
{
const [parkingSpaces,setparkingSpaces] = useState([])
const[term,setTerm] = useState('')
let userLatitude = 0
let userLongitude = 0
const customData = require("./MarkersText.json")
const searchApi = async() => {
const response = await camdenParking.get("",{
params:{
//longitude:-0.115444,
//latitude:51.517597
postcode: term
}
}) // you can change this later on
console.log(response.data)
setparkingSpaces(response.data)
console.log(term)
}
const findCoordinates = () => {
navigator.geolocation.getCurrentPosition(
position => {
const locationString = JSON.stringify(position); // Here we get the JSON object but it needs to be parsed
var longLat = JSON.parse(locationString); // Here we parse the JSON object
userLatitude=longLat.coords.latitude
userLongitude=longLat.coords.longitude
console.log(userLatitude) // This prints the current latitude from the user
console.log(userLongitude) // This prints the longitude
},
error => Alert.alert(error.message),
{ enableHighAccuracy: false, timeout: 20000, maximumAge: 1000 }
);
};
//useEffect(()=>{
// searchApi()
//},[])
return(
<View style={styles.container}>
<SearchBar
term={term}
onTermChange={newTerm=>setTerm(newTerm)}
onTermSubmit={()=> searchApi(term)}
/>
<MapView
style={styles.mapStyle}
initialRegion={{
latitude: 51.524300,
longitude: -0.037790,
latitudeDelta: 0.0122,
longitudeDelta: 0.0421,
}}
>
{parkingSpaces.map((val, index) => {
return (<MapView.Marker
coordinate={{
latitude: parseInt(val.latitude),
longitude:parseInt(val.longitude)
}}
key={index}
title = {"parking markers"}
/>);
})}
</MapView>
<Text>We have found {parkingSpaces.length} results</Text>
<Button onPress={searchApi} title=" Click Here To Get Parking Spaces" />
<Button onPress={findCoordinates} title=" Click Here To Get User's Location" />
<Text> WC2A 3PD</Text>
<Text>Parking Spaces found around {term}</Text>
<FlatList
data = {parkingSpaces}
renderItem={({ item }) => {
return <MapView.Marker
coordinate={{
latitude: parseInt(item.latitude),
longitude:parseInt(item.longitude),
latitudeDelta:0.0,
longitudeDelta:0.0
}}
title = {"parking markers"}
description = {"parking"}
/>
}}
keyExtractor={item => item.unique_identifier}
/>
<FlatList
data = {parkingSpaces}
renderItem={({ item }) => {
return <Text> {item.road_name} | Possible Available Spaces:{item.parking_spaces} </Text>
}}
keyExtractor={item => item.unique_identifier}
/>
</View>
);
};
const styles = StyleSheet.create(
{
container:{
flex:1,
backgroundColor: '#fff',
//alignItems: 'center',
//justifyContent: 'center',
//...StyleSheet.absoluteFillObject,
//marginLeft:0,
//height:400,
//width:400,
//justifyContent:"flex-end",
//alignItems:"center",
},
mapStyle: {
width: 400,
height:400,
//width: Dimensions.get('window').width,
//height: Dimensions.get('window').height,
},
}
)
export default HomeScreen

The first problem is the use of FlatList as container for your markers. The solution is to map over your parkingSpaces array in between your MapView. The second problem is that you call parseInt on your coordinates, which causes the map to not render your markers at all. In addition you would lose precision.
Code:
<MapView
style={styles.mapStyle}
initialRegion={{
latitude: 51.524300,
longitude: -0.037790,
latitudeDelta: 0.0122,
longitudeDelta: 0.0421,
}}
>
{parkingSpaces.map((val, index) => {
return (<MapView.Marker
coordinate={{
latitude: val.latitude,
longitude: val.longitude
}}
key={index}
title = {"parking markers"}
/>);
})}
</MapView>
Working Demo:
https://snack.expo.io/#tim1717/mature-croissant

Related

marker pin recreate on custom marker when user filter the marker then zoom in /out (Please Go through the below Description)

At first, render everything works fine, but as soon as a user tries to filter marker through rest api after this step user zoom out or zoom in a map default marker pin generate on custom marker
dependence:- react-native-maps
check the recording video:-
Video Link
<MapView
ref={mapRef}
rotateEnabled={false}
shouldRasterizeIOS
mapType="standard"
style={styles.map}
initialRegion={INITIAL_REGION}
>
{data &&
data?.map(item => (
<CustomMarker
item={item}
key={item?.id}
setSelectedMarkerId={(row: any) => {
mapRef?.current?.animateToRegion(
{
latitude: Number(row?.lat),
longitude: Number(row?.long),
latitudeDelta: 0.002,
longitudeDelta: 0.002,
},
1000,
);
}}
coordinate={{
latitude: Number(item?.lat),
longitude: Number(item?.long),
}}
/>
))}
</MapView>
here is my custom Marker Code:-
const CustomMarker = ({ item, setSelectedMarkerId, setIsMarkerDetailShow , coordinate }) => {
const [tracksViewChanges, setTracksViewChanges] = useState(true);
return (
<Marker
tracksViewChanges={tracksViewChanges}
coordinate={coordinate}
onPress={() => {
setSelectedMarkerId(item);
// setIsMarkerDetailShow(true);
}}
>
<View>
{item?.abribois ? (
<Image
source={require('src/assets/images/greenMarker.png')}
style={{
height: 30,
width: 30,
resizeMode: 'contain',
}}
onLoadEnd={() => setTracksViewChanges(false)}
/>
) : (
<Image
source={require('src/assets/images/blueMarker.png')}
style={{
height: 30,
width: 30,
resizeMode: 'contain',
}}
onLoadEnd={() => setTracksViewChanges(false)}
/>
)}
</View>
</Marker>
);
};
export default CustomMarker;
this issue to be connected with react-native-reanimated.
after some research i found this solution and its worked for me
react-native-maps-reanimated-issue-patches
See this Examaple
diff --git a/node_modules/react-native-reanimated/ios/LayoutReanimation/REAUIManager.mm b/node_modules/react-native-reanimated/ios/LayoutReanimation/REAUIManager.mm
index 16ed327..a6afa84 100644
--- a/node_modules/react-native-reanimated/ios/LayoutReanimation/REAUIManager.mm
+++ b/node_modules/react-native-reanimated/ios/LayoutReanimation/REAUIManager.mm
## -14,6 +14,9 ##
#if __has_include(<RNScreens/RNSScreen.h>)
#import <RNScreens/RNSScreen.h>
#endif
+#if __has_include("AIRMapMarker.h")
+#import "AIRMapMarker.h"
+#endif
#interface RCTUIManager (REA)
- (void)_manageChildren:(NSNumber *)containerTag
## -125,6 +128,9 ## - (void)_manageChildren:(NSNumber *)containerTag
if ([toRemoveChild isKindOfClass:[RCTModalHostView class]]
#if __has_include(<RNScreens/RNSScreen.h>)
|| ([toRemoveChild isKindOfClass:[RNSScreenView class]])
+#endif
+#if __has_include("AIRMapMarker.h")
+ || ([toRemoveChild isKindOfClass:[AIRMapMarker class]])
#endif
) {
// we don't want layout animations when removing modals or Screens of native-stack since it brings buggy

react-native not updating MapView initialRegion with react-native-geolocation-service

I would like to update my map to show the user location. Using the code below, I get a world map not a map of the UK, which is what the latitude and longitude should show, can anyone help?
const [location, setLocation] = useState({
initialPosition: {
latitude: 0,
longitude: 0,
latitudeDelta: 0,
longitudeDelta: 0,
},
});
const getLocationPermissions = async () => {
const granted = await request(
Platform.select({
android: PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION,
ios: PERMISSIONS.IOS.LOCATION_WHEN_IN_USE,
}),
{
title: 'DemoApp',
message: 'App would like access to your location ',
}
);
return granted === RESULTS.GRANTED;
};
useEffect(() => {
//  check permission
const isGranted = getLocationPermissions();
if (isGranted) {
// get location
Geolocation.getCurrentPosition((info) => {
let lat = info.coords.latitude;
let long = info.coords.longitude;
// update state with location,latitude: 52.62869394486038
//longitude: -1.9794797216434805
var initialRegion = {
latitude: lat,
longitude: long,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
};
});
} else {
console.log('error');
}
}, []);
return (
<View style={styles.container}>
<MapView style={styles.map} initialRegion={location.initialPosition} />
</View>
);
I am guessing you are using react-native-maps MapView Component, it has a showsUserLocation boolean property.
<MapView
style={styles.map}
showsUserLocation={true}
initialRegion={location.initialPosition}
/>
Perhaps this would resolve it?
After retrieve user location from device, animate map to that region.
import * as React from "react";
import { Text, View, StyleSheet } from "react-native";
import MapView from "react-native-maps";
const App = () => {
const mapRef = React.useRef(null);
React.useEffect(() => {
// Below are mocked location in UK. Retrieve real location
// from device with Geoocation API
// latitude: 52.62869394486038
//longitude: -1.9794797216434805
const userRegion = {
latitude: 52.62869394486038,
longitude: -1.9794797216434805,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
};
mapRef.current?.animateToRegion(userRegion);
}, []);
return (
<View style={styles.container}>
<MapView
ref={mapRef}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
style={styles.mapStyle}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
paddingTop: 10,
backgroundColor: "#ecf0f1",
},
mapStyle: {
...StyleSheet.absoluteFillObject,
},
});
export default App;
Working example snack.
https://snack.expo.dev/#emmbyiringiro/9f04a3

Error "Cannot read property 'map' of undefined" after json fetching

After fetching a json file from server keep getting following mistake
TypeError: Cannot read property 'map' of undefined
I understand that have problems with locationsData, which I'm fetching, but I assumed that it already has an array format due to the format of the parsed data (example, please, see below).
import React, { useState } from "react";
import {
withGoogleMap,
withScriptjs,
GoogleMap,
Marker,
InfoWindow,
} from "react-google-maps";
let locationsData;
fetch("http:///locations")
.then(function (u) {
return u.json();
})
.then(function (json) {
locationsData = json;
});
function Map() {
const [selectedLoc, setSelectedLoc] = useState(null);
return (
<div className="App">
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 49.55848, lng: 23.312481 }}
>
{locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
{selectedLoc && (
<InfoWindow
position={{
lat: selectedLoc.gps[0],
lng: selectedLoc.gps[1],
}}
onCloseClick={() => {
setSelectedLoc(null);
}}
>
<div>
<h2>{selectedLoc.name}</h2>
</div>
</InfoWindow>
)}
</GoogleMap>
</div>
);
}
const WrappedMap = withScriptjs(withGoogleMap(Map));
export default function App() {
return (
<div style={{ width: "100vw", height: "100vh" }}>
<WrappedMap
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=000`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
Server data example:
[
{
"gps": [11, 11],
"_id": "1",
"name": "Name1"
},
{
"gps": [22, 22],
"_id": "2",
"name": "Name2"
}
]
You will need to use useEffect and do the fetching in there. You will also have to store the data in the state so that the component will re-render once the data are fetched.
function Map() {
const [selectedLoc, setSelectedLoc] = useState(null);
const [locationsData, setLocationsData] = useState([]);
useEffect(() => {
fetch("http:///locations")
.then(function(u) {
return u.json();
})
.then(function(json) {
setLocationsData(json);
});
}, [])
return (
<div className="App">
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 49.55848, lng: 23.312481 }}
>
{locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
{selectedLoc && (
<InfoWindow
position={{
lat: selectedLoc.gps[0],
lng: selectedLoc.gps[1],
}}
onCloseClick={() => {
setSelectedLoc(null);
}}
>
<div>
<h2>{selectedLoc.name}</h2>
</div>
</InfoWindow>
)}
</GoogleMap>
</div>
);
}
before it gets assigned (locationsData = json;), the locationsData is undefined as you stated here in the initial declaration: let locationsData;
so undefined.map() will throw you the error, you can do this to remain a consistent behavior:
let locationsData = [];
or you can have a validation before calling the .map() function:
{Array.isArray(locationsData) && locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
As #Gabriele pointed out, the fetch operation is placed outside of the component. You can do this to ensure the results get assigned correctly and the component will render it:
function Map() {
const [selectedLoc, setSelectedLoc] = useState(null);
const [locationsData, setLocationsData] = useState([]);
useEffect(() => {
fetch("http:///locations")
.then(u => u.json())
.then(json => setLocationsData(json));
}, []); // Empty dependency, acts similar to componentDidMount
return (
<div className="App">
<GoogleMap
defaultZoom={14}
defaultCenter={{ lat: 49.55848, lng: 23.312481 }}
>
{locationsData.map((loc) => (
<Marker
key={loc._id}
position={{
lat: loc.gps[0],
lng: loc.gps[1],
}}
onClick={() => {
setSelectedLoc(loc);
}}
/>
))}
{selectedLoc && (
<InfoWindow
position={{
lat: selectedLoc.gps[0],
lng: selectedLoc.gps[1],
}}
onCloseClick={() => {
setSelectedLoc(null);
}}
>
<div>
<h2>{selectedLoc.name}</h2>
</div>
</InfoWindow>
)}
</GoogleMap>
</div>
);
}
Initialize locationData with empty array..
let locationsData= [];

Create an array of refs (Maximum update depth exceeded)

I am using react-native-maps and I am rendering multiple markers using array.map(). I also have a carousel which is displaying some pictures and info about each marker.
Basically whenever a user clicks on an item in the carousel, the map zooms in to that marker and displays the callout by calling the following function.
markers[index].showCallout()
which will display the call out for that marker. So I need to populate the array with refs so that I can pass in the index which will show the callout when the user moves the carousel.
To start I created an array which will hold some state.
const [markers, setMarkers] = useState([]);
Here is the array.map function which generates all the markers on the map.
{searchResults.map((marker, index) => {
return (
<MapView.Marker
key={marker.key}
ref={(m) => {
setMarkers((markers) => [[...markers], m]);
}}
onPress={() => onMarkerPress(marker, index)}
coordinate={{
latitude: marker.geopoint.latitude,
longitude: marker.geopoint.longitude,
}}>
<Callout>
<Text>{marker.price}</Text>
</Callout>
</MapView.Marker>
);
})}
The error that I am getting is "Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops."
because I am trying to populate the array using this line.
ref={(m) => {setMarkers((markers) => [[...markers], m])}}
Not sure if there is another way to do this.
The below trick seems to work fine if you're using class components
ref={ref => this.state.markers[index] = ref}
but I am using functional components in my app.
Here's the entire code
const HomeScreen = ({navigation}) => {
{
/************ Array for Rendering Items in Carousel */
}
const searchResults = [
{
key: '1',
photographerURL:
'https://images.pexels.com/photos/598917/pexels-photo-598917.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940',
price: 100,
photographerName: 'Brittany',
geopoint: {latitude: 38.8929372, longitude: -77.0025119},
},
{
key: '2',
photographerURL:
'https://images.pexels.com/photos/1264210/pexels-photo-1264210.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
price: 200,
photographerName: 'Franklin',
geopoint: {latitude: 38.8963932, longitude: -77.0030197},
},
{
key: '3',
photographerURL:
'https://images.pexels.com/photos/243757/pexels-photo-243757.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
price: 50,
photographerName: 'Bryan',
geopoint: {latitude: 38.8925739, longitude: -76.9987113},
},
];
/**
* Function to animate map.
* When the user moves the carousel, the map will zoom in to
* the region where that photographer is
*/
const mapRef = useRef(null);
const [carouselRef, setCarouselRef] = useState([]);
const [markers, setMarkers] = useState([]);
console.log(markers);
/**
* Zooms in on the region whenever the carousel item is changed
*/
const onCarouselItemChange = (index) => {
let location = searchResults[index];
{
mapRef.current.animateToRegion({
latitude: location.geopoint.latitude,
longitude: location.geopoint.longitude,
//Zoom Level
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});
}
//markers[index].showCallout();
};
/**
* When a user clicks on the marker, the carousel jumps
* to that particular item
*/
const onMarkerPress = (location, index) => {
mapRef.current.animateToRegion({
latitude: location.geopoint.latitude,
longitude: location.geopoint.longitude,
//Zoom Level
latitudeDelta: 0.01,
longitudeDelta: 0.01,
});
carouselRef.snapToItem(index);
};
return (
<View style={styles.container}>
{/**************** Google Maps *************** */}
<MapView
style={styles.map}
ref={mapRef}
provider={PROVIDER_GOOGLE}
showsUserLocation
followsUserLocation
initialRegion={{
latitude: 38.8929372,
longitude: -77.0025119,
//Zoom Level
latitudeDelta: 0.01,
longitudeDelta: 0.03,
}}>
{searchResults.map((marker, index) => {
return (
<MapView.Marker
key={marker.key}
//ref={(m) => [setMarkers((markers) => [...markers, m])]}
onPress={() => onMarkerPress(marker, index)}
coordinate={{
latitude: marker.geopoint.latitude,
longitude: marker.geopoint.longitude,
}}>
<Callout>
<Text>{marker.price}</Text>
</Callout>
</MapView.Marker>
);
})}
</MapView>
{/***************** Carousel ***********/}
<Carousel
ref={(c) => {
setCarouselRef(c);
}}
data={searchResults}
horizontal
containerCustomStyle={styles.carousel}
onSnapToItem={(index) => onCarouselItemChange(index)}
layout={'default'}
//layoutCardOffset={`50`}
sliderWidth={screenWidth}
itemWidth={screenWidth * 0.8}
itemHeight={400}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
renderItem={({item}) => (
<Item
photographerName={item.photographerName}
uri={item.photographerURL}
price={item.price}
/>
)}
keyExtractor={(item) => item.key}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFill,
},
map: {
...StyleSheet.absoluteFill,
},
carousel: {
position: 'absolute',
bottom: 0,
marginBottom: '5%',
},
});
export default HomeScreen;
I know this topic is old, but I found the solution.
It's due to the functional components architecture in react-native.
The function is called multiple times, so the limit of setState is rapidly reached.
To avoid this, add:
const [markersLoaded,setMarkersLoaded]=useState(false)
Then:
ref={(m) => {
if (!markersLoaded)
{
setMarkers((markers) => [[...markers], m]);
setMarkersLoaded(true);}
}}

How do I set a marker in MapView of React Native

I want to set a marker on MapView in React Native, but I can't find any information through official documents of MapView.
If it is not allowed in that way, how can I use existed react module such as react-googlemaps in React Native?
Thank you #naoufal.
Finally I am able to display markers on map for react native IOS.
<View style={styles.container}>
<MapView style={styles.map}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0,
longitudeDelta: 0.0,
}}
>
<MapView.Marker
coordinate={{latitude: 37.78825,
longitude: -122.4324}}
title={"title"}
description={"description"}
/>
</MapView>
</View>
For map and container styles, I have used following styles:
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
map: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}
});
I have referred following link:
React native IOS- Display Markers on map
You can set markers using the annotations prop.
For example:
var markers = [
{
latitude: 45.65,
longitude: -78.90,
title: 'Foo Place',
subtitle: '1234 Foo Drive'
}
];
<MapView
region={...}
annotations={markers}
/>
import MapView, { Marker } from 'react-native-maps';
<View>
<MapView
style={styles.mapStyle}
initialRegion={{
latitude: 37.78825,
longitude: -122.4324,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
<Marker coordinate = {{latitude: 37.78825,longitude: -122.4324}}
pinColor = {"purple"} // any color
title={"title"}
description={"description"}/>
</MapView>
</View>
For those looking for a dynamic (e.g., from API), rather than hardcoded coordinates; here's the copy/paste snippet from one of the screens automatically generated by Expo CLI, included React Hooks:
import axios from "axios";
import MapView from "react-native-maps";
import { Dimensions, StyleSheet } from "react-native";
import { Marker } from "react-native-maps";
import { Text, View } from "../components/Themed";
export default function TabTwoScreen() {
const [markers, setMarkers] = useState(null);
useEffect(() => {
axios({
method: "GET",
url: "https://API_URL...",
headers: {
Authorization: `Bearer MY_TOKEN_ABC123...`,
Accept: "application/json",
},
})
.then((response) => {
setMarkers(response.data.results);
})
.catch((error) => {
console.log(error);
});
}, []); // "[]" makes sure the effect will run only once.
return (
<View style={styles.container}>
<Text style={styles.title}>Tab Two</Text>
<MapView style={styles.map}>
{markers &&
markers.map((marker: any, index: number) => (
<Marker
key={index}
coordinate={{
latitude: marker.location[1],
longitude: marker.location[0],
}}
title={marker.title}
description={marker.description}
/>
))}
</MapView>
</View>
);
}
const styles = StyleSheet.create({
// Add your styles here...
});
Updated code - 2020 | React Native 0.63
import MapView, { Marker } from "react-native-maps";
<MapView
style={styles.mapStyle}
region={{
latitude: this.state.mapLat,
longitude: this.state.mapLong,
latitudeDelta: 0.001663,
longitudeDelta: 0.002001,
}}
onRegionChangeComplete={this.onRegionChange}
>
<Marker
coordinate={{latitude: 51.5078788, longitude: -0.0877321}}
>
</Marker>
</MapView>
According to this issue, it's not exposed yet. You won't be able to use the web-React package either, React Native doesn't work like that.
Two suggestions:
Wait for the above issue to be resolved to get a proper API
Try and use WebView to link to a Google Map with an annotation
I'm not actually certain whether #2 is possible though.
import MapView from 'react-native-maps';
<View style={StyleSheet.absoluteFillObject}>
<MapView style={styles.map}
showsUserLocation //to show user current location when given access
loadingEnabled //to show loading while map loading
style={styles.map}
initialRegion={{
latitude,
longitude,
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
>
{
locations && locations.map((location, index) => {
const {
coords: { latitude, longitude }
} = location;
return (
<MapView.Marker
key={index}
coordinate={{ latitude, longitude }}
title={"title"}
description={"address"}
// onPress={this.onMarkerPress(location)}
/>
)
})
}
</MapView>
</View>```
const styles = StyleSheet.create({
map: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
}
});
"dependencies": {
"native-base": "^2.13.8",
"react": "16.9.0",
"react-native": "0.61.2",
"react-native-maps": "git+https://git#github.com/react-native-community/react-native-maps.git"
},
Try using this. Hope it helps to mark for many locations. Happy Coding.
Thank you #zia_qureshi. Finally I am able to display markers on map for react native android.
import MapView, { Marker } from "react-native-maps";
const App = () => {
const [region, setRegion] = useState({
latitude: 51.5078788,
longitude: -0.0877321,
latitudeDelta: 0.009,
longitudeDelta: 0.009
});
return (
<MapView
style={{ flex: 1 }}
region={region}
onRegionChangeComplete={region => setRegion(region)}
>
<Marker coordinate={{ latitude: 51.5078788, longitude: -0.0877321 }} />
</MapView>
);
};
export default App;

Categories