I have a <MapView> and the region never updates when I scroll the map. The map is essentially stuck on one region. When I scroll it seems to pass the exact same region to this.props.onRegionChange which prevents the map from scrolling. How do I make it pass in a scrolled to region?
<MapView
style={styles.map}
region={this.props.region}
onRegionChange={this.props.onRegionChange}
>
{
this.props.markers.map(marker => {
return (
<MapView.Marker
coordinate={{ latitude: marker.latitude, longitude: marker.longitude }}
title={marker.name}
/>
)
})}
</MapView>
full code:
Map.js
import { StyleSheet } from 'react-native'
import React, { Component } from 'react'
import MapView from 'react-native-maps'
import { connect } from 'react-redux'
import {
Button,
Container
} from 'native-base'
import selectMarkers from './markers.selector'
import { updateRegion } from './map.action'
import Icon from 'react-native-vector-icons/FontAwesome'
import { toggleMenu } from '../search-page/searchPage.action'
import mapStyle from './style'
const mapStateToProps = (state) => ({
region: state.get('map').get('region'),
markers: selectMarkers(state)
})
const mapDispatchToProps = (dispatch) => ({
onRegionChange: (region) => {
dispatch(updateRegion(region))
},
onToggleMenuClick: () => {
dispatch(toggleMenu())
}
})
class Map extends Component {
componentDidMount() {
const { store } = this.context
this.unsubscribe = store.subscribe(() => { })
}
componentWillUnmount() {
this.unsubscribe()
}
render() {
console.log('map')
console.log('markers', this.props.markers)
return (
<Container>
<MapView
style={styles.map}
region={this.props.region}
onRegionChange={this.props.onRegionChange}
>
{
this.props.markers.map(marker => {
return (
<MapView.Marker
coordinate={{ latitude: marker.latitude, longitude: marker.longitude }}
title={marker.name}
/>
)
})}
</MapView>
<Button
small
icon
style={mapStyle.toggleMenuButton}
onPress={() => this.props.onToggleMenuClick()}>
<Icon name="sliders" size={20} color="#FFFFFF" />
</Button>
</Container>
)
}
}
Map.contextTypes = {
store: React.PropTypes.object
}
Map.propTypes = {
region: React.PropTypes.shape({
latitude: React.PropTypes.number,
longitude: React.PropTypes.number,
latitudeDelta: React.PropTypes.number,
longitudeDelta: React.PropTypes.number
}).isRequired,
onRegionChange: React.PropTypes.func.isRequired,
onToggleMenuClick: React.PropTypes.func.isRequired,
markers: React.PropTypes.array
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Map)
const styles = StyleSheet.create({
map: {
...StyleSheet.absoluteFillObject,
zIndex: -1
}
})
map.reducer
// #flow
import initialState from '../../config/config'
import { UPDATE_REGION } from './map.action'
const map = (
initialMapState: [] = initialState.get('map'),
action: Object): string => {
switch (action.type) {
case UPDATE_REGION: {
if (action.payload) {
return initialMapState.set('region', {
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
latitude: action.payload.region.latitude,
longitude: action.payload.region.longitude
})
} else {
return initialMapState
}
}
default:
return initialMapState
}
}
export default map
Use onRegionChangeComplete
<MapView
style={styles.map}
region={this.props.region}
onRegionChangeComplete={this.props.onRegionChange}>
The examples in the docs use onRegionChange. So maybe onRegionChange works for most. Maybe it works without redux. Anyway easy fix is onRegionChangeComplete if getting the same issue.
Related
I have a map embedded on my site using "google-map-react". I need to implement adding custom markers to the map. To prescribe coordinates in the code and after saving the marker appears on the map. How can this be implemented?
import GoogleMapReact from "google-map-react";
const Map = () => {
const defaultProps = {
center: {
lat: 10.99835602,
lng: 77.01502627,
},
zoom: 11,
};
return (
<div>
<div style={{ height: "100vh", width: "100%" }}>
<GoogleMapReact
bootstrapURLKeys={{ key: "" }}
defaultCenter={defaultProps.center}
defaultZoom={defaultProps.zoom}
></GoogleMapReact>
</div>
</div>
);
};
export default Map;
you can use #react-google-maps/api library and implement it like this:
import React from 'react'
import { GoogleMap, Marker, useJsApiLoader } from '#react-google-maps/api';
const MapComponent = (props) => {
const { location, zoom } = props;
const containerStyle = {
width: '100%',
height: '95vh'
};
var { isLoaded } = useJsApiLoader({
id: 'google-map-script',
googleMapsApiKey: /* Your API key */
})
return isLoaded ?
<GoogleMap
mapContainerStyle={containerStyle}
defaultCenter={location}
defaultZoom={zoom}
>
<Marker
position={location}
/>
</GoogleMap>
: <></>
}
export default MapComponent;
I'm having an issue. I am getting the error: undefined is not an object (evaluating '_route$params.originPlace').
import { View, Text, Dimensions } from "react-native";
import React from "react";
import HomeMap from "../components/HomeMap/HomeMap";
import RideTypes from "../components/RideTypes/RideTypes";
import styles from "./styles.js";
import RouteMap from "../components/RouteMap/RouteMap";
import { useRoute } from "#react-navigation/native";
import { useNavigation } from "#react-navigation/native";
const SearchResult = (props) => {
const navigation = useNavigation();
const route = useRoute();
console.log(route.params);
const { originPlace, destinationPlace } = route.params;
return (
<View>
<View style={{ height: Dimensions.get("window").height - 400 }}>
<RouteMap origin={originPlace} destination={destinationPlace} />
</View>
<View>
<RideTypes />
</View>
</View>
);
};
export default SearchResult;
Heres the other file where I m taking the origin and destination. But I don't know what is wrong in here. I m not able to figure out. Help!
import { View, Text, Image, FlatList } from "react-native";
import React from "react";
import MapView, { PROVIDER_GOOGLE, Marker } from "react-native-maps";
import cars from "../../../assets/data/cars";
import MapViewDirections from "react-native-maps-directions";
import {GOOGLE_MAPS_APIKEY} from "#env";
const RouteMap = ({origin,destination}) => {
const originLoc = {
latitude: origin.details.geometry.location.lat,
longitude: origin.details.geometry.location.lng,
}
const destinationLoc = {
latitude:destination.details.geometry.location.lat,
longitude:destination.details.geometry.location.lng,
}
console.log(originLoc);
return (
<MapView
style={{ width: "100%", height: "100%" }}
provider={PROVIDER_GOOGLE}
showsUserLocation={true}
initialRegion={{
latitude: 28.450627,
longitude: -16.263045,
latitudeDelta: 0.0222,
longitudeDelta: 0.0421,
}}
>
<MapViewDirections
origin={originLoc}
destination={destinationLoc}
apikey={GOOGLE_MAPS_APIKEY}
strokeWidth={3}
strokeColor="hotpink"
/>
<Marker
coordinate={originLoc}
title={'Origin'}
/>
<Marker
coordinate={destinationLoc}
title={'Destination'}
/>
</MapView>
);
};
export default RouteMap;
And here is the destination Search js file which will redirect to search result once origin and destination selected from google apis.
import { View, Text, TextInput, SafeAreaView } from 'react-native';
import React, { useEffect, useState } from 'react';
import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";
import { GOOGLE_MAPS_APIKEY } from "#env";
import { useNavigation } from '#react-navigation/native';
import styles from './styles';
import PlaceRow from './PlaceRow.js';
const DestinationSearch = (props) => {
navigation = useNavigation();
const homePlace = {
description: 'Home',
geometry: { location: { lat: 48.8152937, lng: 2.4597668 } },
};
const workPlace = {
description: 'Work',
geometry: { location: { lat: 48.8496818, lng: 2.2940881 } },
};
const checkNavigation = () => {
if (originPlace && destinationPlace) {
navigation.navigate('SearchResult'), {
originPlace,
destinationPlace,
}
}
}
const [originPlace, setOriginPlace] = useState( null ) ;
const [destinationPlace, setDestinationPlace] = useState( null );
useEffect(() =>{
checkNavigation();
}, [originPlace,destinationPlace]);
return (
<SafeAreaView>
<View style= {styles.container}>
{/* From */}
<GooglePlacesAutocomplete
backgroundColor= "#eee"
nearbyPlacesAPI="GooglePlacesSearch"
placeholder="From"
styles={{
textInput: styles.textInput,
container: styles.autoCompleteContainer,
listView: styles.listView,
separator: styles.separator,
}}
onPress={(data , details = null) => {
setOriginPlace({data, details});
}}
renderRow={(data) =><PlaceRow data={data}/>}
fetchDetails={true}
enablePoweredByContainer={false}
currentLocation={true}
currentLocationLabel='Current Location'
query={{
key: GOOGLE_MAPS_APIKEY,
language: "en",
}}
renderRow={(data) => <PlaceRow data={data}/>}
renderDescription={(data) => data.description || data.vicinity}
predefinedPlaces={[homePlace, workPlace]}
/>
{/* Where To */}
<GooglePlacesAutocomplete
backgroundColor= "#eee"
nearbyPlacesAPI="GooglePlacesSearch"
placeholder="Where To?"
styles={{
textInput: styles.textInput,
container: {
...styles.autoCompleteContainer,
top: 50},
listView: {...styles.listView,
top: 50,
},
separator: styles.separator,
}}
onPress={(data , details = null) => {
setDestinationPlace({data, details});
}}
renderRow={(data) =><PlaceRow data={data}/>}
fetchDetails={true}
returnKeyType={"Search"}
enablePoweredByContainer={false}
query={{
key: GOOGLE_MAPS_APIKEY,
language: "en",
}}
/>
{/* Circle near origin Input */}
<View style = {styles.circle}/>
{/* Line between dots */}
<View style = {styles.line}/>
{/* Square near destination Input */}
<View style = {styles.square}/>
</View>
</SafeAreaView>
)
}
export default DestinationSearch;
The Mistake was in DestinationSearch
Mistake:
const checkNavigation = () => {
if (originPlace && destinationPlace) {
navigation.navigate('SearchResult'), {
originPlace,
destinationPlace,
}
}
}
Solution:
const checkNavigation = () => {
if (originPlace && destinationPlace) {
navigation.navigate("SearchResult",
{
originPlace,
destinationPlace,
})
}
}
I'm trying to understand how modal it works in React Native
What I want, it's when I click on marker, it display me the different information of specific marker (title, description, name).
What I have:
export default class MapsScreen extends React.Component {
state = { reports: [] }
componentDidMount() {
// call api
}
mapMarkers = () => {
return this.state.reports.map((report) => <Marker
key={report.key}
title={report.name}
coordinate={{ latitude: report.latitude, longitude: report.longitude }}
title={report.name}
description={report.description}
onPress={this._onMarkerPress.bind(this, this.state.reports.filter(r => r.key === report.key ))}
>
</Marker >)
}
render() {
return (
<MapView
style={{ ...StyleSheet.absoluteFillObject }}
initialRegion={{
latitude: 52.0,
longitude: -0.98,
latitudeDelta: 10,
longitudeDelta: 5
}} >
{this.mapMarkers()}
</MapView>
);
}
_onMarkerPress (markerData) {
console.log(JSON.stringify(markerData));
}
}
How can I start for do What I want ?
Thanks for your help :)
I have a problem with displays icons on google map.
Here is my code:
import React, { Component } from 'react'
import { compose, withProps, withStateHandlers } from 'recompose'
import { withScriptjs, withGoogleMap, GoogleMap, Marker, InfoWindow } from 'react-google-maps'
import MapStyles from './data/MapStyles'
export const Map = compose(
withStateHandlers(() => ({
isOpen: false,
}), {
onToggleOpen: ({ isOpen }) => () => ({
isOpen: !isOpen,
})
}),
withScriptjs,
withGoogleMap
)(props => {
return (
<GoogleMap
defaultZoom={13}
defaultCenter={{ lat: 52.229676, lng: 21.012229 }}
defaultOptions={{ styles: MapStyles }}
mapTypeControl={false}
>{ props.markers.map(marker => {
console.log(marker.location);
<Marker
{...marker}
key={marker.place_id}
position={marker.location}
title={marker.title}
icon={{
url: 'icons/icon.png'
}}
onClick={props.onToggleOpen}
>
{props.isOpen &&
<InfoWindow onCloseClick={props.onToggleOpen}>
<div>Open</div>
</InfoWindow>}
</Marker>
})}
</GoogleMap>
);})
export default Map
Positions for markers are displayed in console by console.log, but they don't display on a map ... I don't know why .... Maybe some of you know, why is this happen ... Here is link to this project on Github: https://github.com/hajczek/Neighborhood---Warsaw-Cultural-Map
Thanks for any hints.
Your missing a return in the map projection -
>{ props.markers.map(marker => {
console.log(marker.location);
<Marker
add a return before <Marker
>{ props.markers.map(marker => {
console.log(marker.location);
return <Marker
Working sample on codesandbox
I'm really new in ReactJS. I want to visualize a map of Bulgaria and set markers in each city only when I receive rainfall data. For now I try with examples from this link: React google-maps
But I get an error when placing the code in my file:
106:86-93 "export 'default' (imported as 'RainMap') was not found in './components/RainMap/RainMap'
Probably the error is very small but I do not know how to fix it.
My code:
import React, { Component } from 'react';
import 'react-select/dist/react-select.css';
const google = window.google;
const fetch = require("isomorphic-fetch");
const { compose, withProps, withHandlers } = require("recompose");
const {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
} = require("react-google-maps");
const { MarkerClusterer } = require("react-google-maps/lib/components/addons/MarkerClusterer");
const MapWithAMarkerClusterer = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyC4R6AN7SmujjPUIGKdyao2Kqitzr1kiRg&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withHandlers({
onMarkerClustererClick: () => (markerClusterer) => {
const clickedMarkers = markerClusterer.getMarkers()
console.log(`Current clicked markers length: ${clickedMarkers.length}`)
console.log(clickedMarkers)
},
}),
withScriptjs,
withGoogleMap
)(props =>
<GoogleMap
defaultZoom={3}
defaultCenter={{ lat: 25.0391667, lng: 121.525 }}
>
<MarkerClusterer
onClick={props.onMarkerClustererClick}
averageCenter
enableRetinaIcons
gridSize={60}
>
{props.markers.map(marker => (
<Marker
key={marker.photo_id}
position={{ lat: marker.latitude, lng: marker.longitude }}
/>
))}
</MarkerClusterer>
</GoogleMap>
);
class DemoApp extends React.PureComponent {
componentWillMount() {
this.setState({ markers: [] })
}
componentDidMount() {
const url = [
// Length issue
`https://gist.githubusercontent.com`,
`/farrrr/dfda7dd7fccfec5474d3`,
`/raw/758852bbc1979f6c4522ab4e92d1c92cba8fb0dc/data.json`
].join("")
fetch(url)
.then(res => res.json())
.then(data => {
this.setState({ markers: data.photos });
});
}
render() {
return (
<MapWithAMarkerClusterer markers={this.state.markers} />
)
}
}
<DemoApp />
You didn't import your RainMap component. Where in your directory is it stored? It seems to be trying to import from components folder -> RainMap folder -> RainMap.js