Integrating the google map component with the react HOC? - reactjs

import React,{Component } from 'react';
import {
withGoogleMap,
GoogleMap,
withScriptjs,
Marker,
InfoWindow,
} from 'react-google-maps';
import {compose, withProps, withStateHandlers} from 'recompose';
import places from 'places.json';
class MapComponent extends Component {
constructor (props) {
super (props);
this.state = {
zoom: 11,
center: {lat: 29.969516, lng: -90.103866},
markers: [],
lat:'',
lng:'',
markersLoaded: false,
};
}
componentDidMount () {
let geocoder = new window.google.maps.Geocoder ();
geocoder.geocode ({address: 'Bakerstreet, 2'}, function (results, status) {
if (status == 'OK') {
this.setState ({
lat: results[0].geometry.location.lat (),
lng: results[0].geometry.location.lng (),
});
} else {
console.log (
'Geocode was not successful for the following reason:',
status
);
}
});
}
render () {
const { lat, lng } = this.state;
const GoogleMapExample = withGoogleMap (props => (
<GoogleMap
defaultZoom={props.zoom}
defaultCenter={props.center}
options={{styles: props.mapdynamic ? darkThemeStyle : lightThemeStyle}}
>
{props.places &&
props.places.map ((place, i) => {
let lat = parseFloat (place.latitude, 10);
let lng = parseFloat (place.longitude, 10);
return (
<Marker
id={place.id}
key={place.id}
position={{lat: lat, lng: lng}}
icon="http://maps.google.com/mapfiles/ms/icons/blue-dot.png"
onMouseOver={props.onToggleOpen.bind (this, i)}
>
{props.infoWindows[i].isOpen &&
<InfoWindow onCloseClick={props.onToggleOpen.bind (i)}>
<div>{place.name}</div>
</InfoWindow>}
</Marker>
);
})}
</GoogleMap>
));
return (
<div>
<GoogleMapExample
center={{lat: 40.6451594, lng: -74.0850826}}
zoom={10}
places={places} />
</div>
);
}
}
export default compose (
withProps ({
googleMapURL: 'https://maps.googleapis.com/maps/api/js?key=YOUR KEY&libraries=geometry,drawing,places',
loadingElement: <div style={{height: `100%`}} />,
containerElement: (
<div style={{height: '100%', width: '100%', padding: '10px'}} />
),
mapElement: <div style={{height: '100%'}} />,
}),
withStateHandlers (
props => ({
infoWindows: props.places.map (p => {
return {isOpen: false};
}),
}),
{
onToggleOpen: ({infoWindows}) => selectedIndex => ({
infoWindows: infoWindows.map ((iw, i) => {
iw.isOpen = selectedIndex === i;
return iw;
}),
}),
}
),
withScriptjs,
withGoogleMap
) (MapComponent);
I am here by writing the google map component using the react order component.
But when I am trying to run this I am getting some kind of error.
Could you some one take a look into it and let me know what are the
issues here. I am getting following error like Invariant Violation:
Required props containerElement or mapElement is missing. You need to
provide both of them. The google.maps.Map instance will be
initialized on mapElement and it's wrapped by containerElement. You
need to provide both of them since Google Map requires the DOM to have
height when initialized.
Regards

You have additionally used withGoogleMap hoc in render method which you don't need
render () {
const { lat, lng } = this.state;
return (
<GoogleMap
defaultZoom={10}
defaultCenter={{lat: 40.6451594, lng: -74.0850826}}
options={{styles: props.mapdynamic ? darkThemeStyle : lightThemeStyle}}
>
{places &&
places.map ((place, i) => {
let lat = parseFloat (place.latitude, 10);
let lng = parseFloat (place.longitude, 10);
return (
<Marker
id={place.id}
key={place.id}
position={{lat: lat, lng: lng}}
icon="http://maps.google.com/mapfiles/ms/icons/blue-dot.png"
onMouseOver={props.onToggleOpen.bind (this, i)}
>
{props.infoWindows[i].isOpen &&
<InfoWindow onCloseClick={props.onToggleOpen.bind (i)}>
<div>{place.name}</div>
</InfoWindow>}
</Marker>
);
})}
</GoogleMap>
);
}

Related

How can implement react-google-maps DirectionsRenderer in my project

I am building a simple project that if a user clicks a button it should show directions from the user's location to the destination which I mark. Here is my code.
I have just implemented some parts but I did not understand how to implement DirectionsRenderer and could not learn from articles, docs. Now I have no idea what to do. Can anyone explain me in a easier way? Thank you!
GoogleMap,
withGoogleMap,
withScriptjs,
DirectionsRenderer,
} from 'react-google-maps';
import Marker from 'react-google-maps/lib/components/Marker';
function Map() {
return (
<div className='App'>
<GoogleMap
defaultZoom={10}
defaultCenter={{ lat: 51.507351, lng: -0.127758 }}
>
<Marker position={{ lat: 51.4666, lng: -0.213 }} />
</GoogleMap>
</div>
);
}
const DirectionsService = new window.google.maps.DirectionsService();
DirectionsService.route({
origin: new window.google.maps.LatLng(41.85073, -87.65126),
destination: new window.google.maps.LatLng(41.85258, -87.65141),
travelMode: window.google.maps.TravelMode.DRIVING,
});
const WrappedMap = withScriptjs(withGoogleMap(Map));
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=${process.env.REACT_APP_MAP_KEY}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
export default App;
Here are the steps I made to achieve your use-case:
Use the browser's HTML5 Geolocation feature to get the user's current position inside the componentDidMount.
Then use state variables to hold the value of the current location. You also put the value of the user current location state to center parameter of your GoogleMap object so that the map will show the area of the map where the user is. This will be used as the origion of your Directions service.
3.Also use another state to hold the user current location. This is to be used as state to put a marker in the user current location.
Call a function inside the onClick parameter of your GoogleMap object. Then use another state variable that will hold the value of the clicked coordinates. This will be used as the destination of the Directions Service.
Put a button on top of your map div and call a function inside its OnClick parameter.The function will call the GoogleMaps directionsService and will calculate a route between your origin and destination. If there's a route, you use another state variable to hold the result of the Directions service.
Use the DirectionsRenderer object inside the GoogleMap object to display the polyline of the route.
Here's the sample code (Note: Make sure to put your API key in the index.js for the sample to work) and the code snippet below:
/*global google*/
import React, { Component } from 'react';
import Button from 'react-bootstrap/Button';
import {
withGoogleMap,
Marker,
GoogleMap,
DirectionsRenderer
} from 'react-google-maps';
class Map extends Component {
state = {
directions: null,
markerPos: null,
centerMarker: null,
currentLocation: null
};
componentDidMount = () => {
navigator?.geolocation.getCurrentPosition(
({ coords: { latitude: lat, longitude: lng } }) => {
const pos = { lat, lng };
this.setState({ currentLocation: pos, centerMarker: pos });
}
);
};
onMapClick = e => {
this.setState({ markerPos: e.latLng });
};
getDirections = () => {
const directionsService = new google.maps.DirectionsService();
const origin = this.state.currentLocation;
const destination = this.state.markerPos;
if (origin !== null && destination !== null) {
directionsService.route(
{
origin: origin,
destination: destination,
travelMode: google.maps.TravelMode.DRIVING
},
(result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.setState({
directions: result
});
} else {
console.error(`error fetching directions ${result}`);
}
}
);
} else {
console.log('Please mark your destination in the map first!');
}
};
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
defaultCenter={{ lat: 40.756795, lng: -73.954298 }}
defaultZoom={13}
center={this.state.currentLocation}
onClick={this.onMapClick}
>
{this.state.centerMarker !== null && (
<Marker position={this.state.centerMarker} label={'userloc'} />
)}
{this.state.markerPos !== null && (
<Marker position={this.state.markerPos} />
)}
{this.state.directions !== null && (
<DirectionsRenderer
directions={this.state.directions}
defaultOptions={{
suppressMarkers: true
}}
/>
)}
</GoogleMap>
));
return (
<div>
<Button onClick={this.getDirections}>Get Direction</Button>
<GoogleMapExample
containerElement={<div style={{ height: `500px`, width: '500px' }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;

Get details of all the Markers covered under a drawn polygon or any shape using react-google-maps

I am using react-google-maps. I have created map and displayed 3 types of markers in it.
I can now draw polygons on map but not able to get the details of markers covered under the drawn shape.
Any help would be appreciated.
This is my code of map jsx.
I am creating 3 different markers with different icons to identify on map.
When i draw a shape on map, i want to get the details of every sort of marker which comes under the drawn shape.
import React from "react";
import DrawingManager from "react-google-maps/lib/components/drawing/DrawingManager";
import {GoogleMap, InfoWindow, Marker, withGoogleMap, withScriptjs} from "react-google-maps";
import UploadApis from "../../service/rest/upload";
import "./index.scss";
let selectedShape;
function clearSelection() {
if (selectedShape) {
if (selectedShape.type !== 'marker') {
selectedShape.setEditable(false);
}
selectedShape = null;
}
}
function setSelection(shape) {
if (shape.type !== 'marker') {
clearSelection();
shape.setEditable(true);
}
selectedShape = shape;
}
class Map extends React.Component {
constructor(props) {
super(props);
this.shapes = [];
this.state = {
fiberData: [],
subscriberData: [],
sitesData: [],
fetchData: false,
selected: null
};
this.handleOverlayComplete = this.handleOverlayComplete.bind(this);
this.data();
}
handleOverlayComplete(e) {
console.log("overlay",e);
const newShape = e.overlay;
newShape.type = e.type;
if (e.type !== window.google.maps.drawing.OverlayType.MARKER) {
window.google.maps.event.addListener(newShape, 'click', function (e) {
if (e.vertex !== undefined) {
if (newShape.type === window.google.maps.drawing.OverlayType.POLYGON) {
let path = newShape.getPaths().getAt(e.path);
path.removeAt(e.vertex);
if (path.length < 3) {
newShape.setMap(null);
}
}
if (newShape.type === window.google.maps.drawing.OverlayType.POLYLINE) {
let path = newShape.getPath();
path.removeAt(e.vertex);
if (path.length < 2) {
newShape.setMap(null);
}
}
}
setSelection(newShape);
});
setSelection(newShape);
} else {
window.google.maps.event.addListener(newShape, 'click', function (e) {
setSelection(newShape);
});
setSelection(newShape);
}
this.shapes.push(newShape);
}
data = async () => {
let fiberData = await UploadApis.getMetaDataById("fiber",this.props.projectId);
let sitesData = await UploadApis.getMetaDataById("sites",this.props.projectId);
let subscriberData = await UploadApis.getMetaDataById("subscriber",this.props.projectId);
this.setState({fiberData: fiberData, sitesData: sitesData, subscriberData: subscriberData, fetchData: true})
};
deleteSelectedShape = () => {
if (selectedShape) {
selectedShape.setMap(null);
}
};
setSelected(selected) {
this.setState({selected: selected})
}
render() {
return (
<div>
<button className="btn-container" onClick={this.deleteSelectedShape}>Delete Shape
</button>
{this.state.fetchData ?
<div>
<GoogleMap
defaultZoom={6}
defaultCenter={{lat: 22.5106879, lng: 79.9189213}}
>
<DrawingManager
defaultDrawingMode={null}
defaultOptions={{
drawingControl: true,
drawingControlOptions: {
position: window.google.maps.ControlPosition.TOP_CENTER,
drawingModes: [ 'circle', 'polygon', 'polyline', 'rectangle']
},
polygonOptions: {editable: true},
circleOptions: {editable: true},
rectangleOptions: {editable: true},
markerOptions: {editable: true},
polylineOptions: {editable: true}
}}
onOverlayComplete={this.handleOverlayComplete}
/>
{this.state.fiberData.map((fiber) => (
<Marker
key={fiber.id}
position={{lat: fiber.latitude, lng: fiber.longitude}}
onClick={() => {
this.setSelected(fiber);
}}
icon={{
url: "../assets/svg/fiber.png",
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
))}
{this.state.sitesData.map((site) => (
<Marker
key={site.id}
position={{lat: site.latitude, lng: site.longitude}}
onClick={() => {
this.setSelected(site);
}}
icon={{
url: "../assets/svg/tower.png",
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
))}
{this.state.subscriberData.map((subscriber) => (
<Marker
key={subscriber.id}
position={{lat: subscriber.latitude, lng: subscriber.longitude}}
onClick={() => {
this.setSelected(subscriber);
}}
icon={{
url: "../assets/svg/subscriber.svg",
scaledSize: new window.google.maps.Size(25, 25)
}}
/>
))}
{this.state.selected && (
<InfoWindow
position={{lat: this.state.selected.latitude, lng: this.state.selected.longitude}}
onCloseClick={() => {
this.setSelected(null);
}}>
<div>
<h4>{this.state.selected.name}</h4>
<p>{this.state.selected.description}</p>
</div>
</InfoWindow>
)}
</GoogleMap>
</div> : null
}
</div>
);
}
}
export default withScriptjs(withGoogleMap(Map));
This is the first file which i have called. Index file which renders the map is -
import React from "react";
import Map from './map.jsx';
export default class MapContainer extends React.Component {
_projectId="";
constructor(props) {
super(props);
console.log(props);
if(props.location.state.project){
this._projectId = props.location.state.project.id;
}
}
render() {
return (
<div>
<Map
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=API_KEY`}
loadingElement={<div style={{height: `100%`}}/>}
containerElement={<div style={{height: `480px`}}/>}
mapElement={<div style={{height: `100%`}}/>}
projectId ={this._projectId}
/>
</div>
);
}
}```

React testing with Jest and Enzyme #react-google-maps/api returns TypeError: Cannot read property 'maps' of undefined

I am trying to test a component with #react-google-maps/api package. I am getting error: TypeError: Cannot read property 'maps' of undefined.
My component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPersonId, updatePersonSettings, pushPersonMessage } from '../../actions/person';
import TemplatePage from '../templates/TemplatePage';
import Card from '../partials/Card';
import Msg from '../partials/Msg';
import { GoogleMap, Marker } from '#react-google-maps/api';
import markerPosition from'../../img/marker-position.png';
import PlacesAutocomplete, { geocodeByAddress, getLatLng } from 'react-places-autocomplete';
import PropTypes from 'prop-types';
import { DEFAULT_LAT, DEFAULT_LNG, DEFAULT_ZOOM } from '../../config/';
export class Settings extends Component {
state = {
lat: DEFAULT_LAT,
lng: DEFAULT_LNG,
zoom: DEFAULT_ZOOM,
address: '',
formSubmitted: false
}
componentDidMount () {
const { lat, lng, zoom } = this.props.auth;
this.setState({
lat: lat !== undefined && lat !== null ? lat : DEFAULT_LAT,
lng: lng !== undefined && lng !== null ? lng : DEFAULT_LNG,
zoom: zoom !== undefined && zoom !== null ? zoom : DEFAULT_ZOOM
});
this.drawMarker();
}
handleOnSubmit = e => {
e.preventDefault();
const settings = {
zoom: this.state.zoom,
lat: this.state.lat,
lng: this.state.lng
}
this.props.updatePersonSettings({ id: this.props.auth.person_id, settings })
}
handleChangeZoom = event => {
this.setState({ zoom: parseInt(event.target.value )});
}
handleChangeAddress = (address) => {
this.setState({ address });
}
handleSelect = (address) => {
geocodeByAddress(address)
.then(results =>
getLatLng(results[0])
.then(function(result) {
this.setState({
lat: result.lat,
lng: result.lng,
})
this.drawMarker()
}.bind(this))
)
.catch(error => console.error('Error', error));
};
handleMapClick = e => {
this.setState({
lat: e.latLng.lat(),
lng: e.latLng.lng(),
});
this.drawMarker();
}
handleMapZoom = (zoom) => {
console.log(zoom)
}
drawMarker = () => {
return <Marker
position={{
lat: parseFloat(this.state.lat),
lng: parseFloat(this.state.lng)
}}
icon={
new window.google.maps.MarkerImage(
markerPosition,
null, /* size is determined at runtime */
null, /* origin is 0,0 */
null, /* anchor is bottom center of the scaled image */
new window.google.maps.Size(48, 48)
)
}
>
</Marker>
}
get msg() {
if(this.props.person !== '') {
return <Msg msg={this.props.person} />
}
return null;
}
render() {
const { status } = this.props.person;
const { lat, lng, zoom, address, formSubmitted } = this.state;
return (
<TemplatePage>
{ this.msg }
<Card title='Settings' padding='large'>
<form className="form" onSubmit={this.handleOnSubmit}>
<div className="form-group">
<label htmlFor="position">Default map position</label>
<div className="google-map google-map__settings">
<GoogleMap
center={{ lat, lng }}
zoom={ zoom }
onClick={ e => this.handleMapClick(e) }
onZoomChanged={(e) => {
console.log('zoom changed')
}}
>
{this.drawMarker()}
<div className="map-constraints-container" />
</GoogleMap>
</div>
</div>
<div className="form-group">
<div className="map-constraints-slider">
<label htmlFor="range">Default map zoom: {zoom}</label>
<input
type="range"
id="zoom"
value={ zoom }
name="zoom"
min="1"
max="18"
onChange={ this.handleChangeZoom }
/>
</div>
</div>
<div className="form-group">
<PlacesAutocomplete
value={address}
onChange={ this.handleChangeAddress }
onSelect={ this.handleSelect }
>
{({ getInputProps, suggestions, getSuggestionItemProps, loading }) => (
<div>
<input
{...getInputProps({
placeholder: 'Search places...',
className: 'location-search-input',
})}
/>
<div className="autocomplete-dropdown-container">
{loading && <div>Loading...</div>}
{suggestions.map(suggestion => {
const className = suggestion.active
? 'suggestion-item--active'
: 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div
{...getSuggestionItemProps(suggestion, {
className,
style,
})}
>
<span>{suggestion.description}</span>
</div>
);
})}
</div>
</div>
)}
</PlacesAutocomplete>
</div>
<div className="form-group">
<input
type="submit"
value="Update settings"
className="btn btn--primary card__footer--btn-left"
disabled={ formSubmitted && status === 'fetching' ? 'disabled' : null }
/>
</div>
</form>
</Card>
</TemplatePage>
)
}
}
Settings.defaultProps = {
auth: {},
person: {},
fetchPersonId: () => Promise.resolve(),
updatePersonsettings: () => Promise.resolve(),
pushPersonMessage: () => Promise.resolve()
}
Settings.propTypes = {
auth: PropTypes.object,
person: PropTypes.object,
fetchPersonId: PropTypes.func,
updatePersonsettings: PropTypes.func,
pushPersonMessage: PropTypes.func
};
export default connect(
({ auth, person }) => ({ auth, person }),
{ fetchPersonId, updatePersonSettings, pushPersonMessage }
)(Settings);
My test:
import React from 'react';
import { shallow } from 'enzyme';
import { Settings } from '../../../components/pages/Settings';
test('should render settings page', () => {
const wrapper = shallow(<Settings />);
expect(wrapper).toMatchSnapshot();
});
I read that in order to resolve such issues it is best to mock up the package. In some other component I am using `` package, which I managed to mock like so:
const zxcvbn = require.requireActual('zxcvbn');
export default (password = 'test') => {
return zxcvbn(password);
}
How would I mock up the #react-google-maps/api package and get rid of the error? Is this a good approach (mocking the package)? Or can this be resolved any other way? How would I test if the map or marker rendered at all?
I know this is an old question.
But the way I manage this is by mocking the google object. This is only mocks what I'm calling so you'd need to add any google constants and methods you call.
As for testing if it gets rendered, that's all buried in the google maps javascript api blob. You could add spys to ensure the appropriate functions are called.
I don't think it'd be possible to verify google maps is actually rendering anything though.
import ReactDOM from 'react-dom';
//ReactDOM.createPortal = jest.fn(node => node);
jest.mock('#react-google-maps/api', () => {
const React = require('React');
return {
withGoogleMap: (Component) => Component,
withScriptjs: (Component) => Component,
Polyline: (props) => <div />,
Marker: (props) => <div />,
GoogleMap: (props) => (<div><div className="mock-google-maps" />{props.children}</div>),
};
});
global.google = {
maps: {
LatLngBounds: () => ({
extend: () => { },
}),
MapTypeId: {
ROADMAP: 'rdmap',
SATELLITE: 'stllte'
},
ControlPosition: {
BOTTOM_CENTER: 'BC',
BOTTOM_LEFT: 'BL',
BOTTOM_RIGHT: 'BR',
LEFT_BOTTOM: 'LB',
LEFT_CENTER: 'LC',
LEFT_TOP: 'LT',
RIGHT_BOTTOM: 'RB',
RIGHT_CENTER: 'RC',
RIGHT_TOP: 'RT',
TOP_CENTER: 'TC',
TOP_LEFT: 'TL',
TOP_RIGHT: 'TR',
},
Size: function (w, h) {},
Data: class {
setStyle() {}
addListener() {}
setMap() {}
}
}
};

Use react-google-maps methods with recompose

I'm using react google maps for fine tuning the user location after a geo location function, this is part of my Map.js code:
const MyMapComponent = compose(
withProps({
googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyAKCqAqiyop85LNl9qUb6OAT1lJupLEnzo&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{height: `100%`}}/>,
containerElement: <div style={{height: `400px`}}/>,
mapElement: <div style={{height: `100%`}}/>,
}),
withState(),
withHandlers(() => {
const refs = {
map: undefined,
}
return {
onMapMounted: () => ref => {
refs.map = ref
},
onBoundsChanged: ({onBoundsChanged}) => () => {
onBoundsChanged(refs.map.getCenter().lat(), refs.map.getCenter().lng())
}
}
}),
withScriptjs,
withGoogleMap
)((props) =>
<GoogleMap
defaultZoom={8}
defaultCenter={{lat: props.lat, lng: props.lng}}
ref={props.onMapMounted}
onBoundsChanged={props.onBoundsChanged}
>
<Marker position={{lat: props.lat, lng: props.lng}}/>
</GoogleMap>
)
I just want to be able to call the panTo() method in other component via ref, internally i have no problem cause i think the ref passes fine in the mapMounted method ( refs.map.getCenter().lat() ), but how to call thee methods externally, my prob is that im using recompose library. thx in advance.
part of the code in Home.js where i use map and have the get position method that i want to trigger panTo():
import MyMapComponent from './Maps';
export default class HomeComponent extends React.Component {
render() {
const {showAlert, address, lat, lng} = this.props;
return (
<MyMapComponent
lat={lat}
lng={lng}
onBoundsChanged={this.props.handleOnBoundsChanged}
/>
<Button onClick={()=>this.props.getPosition()}>Usar mi
ubicaciĆ³n actual</Button>
)
}
}
You can create a prop out of any of the map methods.
...
withHandlers(() => {
let map;
return {
onMapMounted: () => ref => {
map = ref;
},
onBoundsChanged: ({ onBoundsChanged }) => () => {
onBoundsChanged(map.getCenter().lat(), map.getCenter().lng());
}
mapPanTo: () => args => map.panTo(args),
};
})
...
Now props.mapPanTo can be passed around to any other component.

Updating child prop breaks connection with parent state

I'm using react-google-maps to display markers on a map. When I use the SearchBox function in the child component to set props.locations my map Markers appear. However, when I use a button in the parent component to update the state of the locations within MapWithASearchBox the child prop doesn't recognise the change. If I reload the page and just use the button on the parent Component the markers appear correct. I assume I'm breaking the connection between child and parent when I set the prop within the child component.
Path: Parent Component MapPage.jsx
export default class MapPage extends Component {
constructor(props) {
super(props);
this.state = {
companies: []
}
this.handleButtonASXMarketCap = this.handleButtonASXMarketCap.bind(this);
}
handleButtonASXMarketCap(limit, e) {
e.preventDefault();
Meteor.call('getASXTop100', limit, (error, result) => {
if (result) {
this.setStateOfCompanies(result);
}
});
}
setStateOfCompanies(data) {
this.setState({
companies: data
})
}
render() {
return (
<div>
<Button color="primary ml-2" onClick={(e) => this.handleButtonASXMarketCap(100, e)}>Top 100 ASX</Button>
<MapWithASearchBox
locations={this.state.companies}
/>
</div>
);
}
}
Path: Child Component MapWithASearchBox.jsx
const MapWithASearchBox = compose(
withProps({
googleMapURL: "myUrl",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
lifecycle({
componentWillMount() {
const refs = {}
this.setState({
bounds: null,
center: {
lat: -23.696248, lng: 133.880731
},
zoom: 4,
markers: [],
onPlacesChanged: () => {
const places = refs.searchBox.getPlaces();
const bounds = new google.maps.LatLngBounds();
places.forEach(place => {
if (place.geometry.viewport) {
bounds.union(place.geometry.viewport)
} else {
bounds.extend(place.geometry.location)
}
});
const nextMarkers = places.map(place => ({
position: place.geometry.location,
}));
const nextCenter = _.get(nextMarkers, '0.position', this.state.center);
this.setState({
center: nextCenter,
markers: nextMarkers,
zoom: 15
});
const lat = nextMarkers.map(x => x.position.lat());
const lng = nextMarkers.map(x => x.position.lng());
Meteor.call('runMethodTest', lat[0], lng[0], (error, result) => {
if (result) {
this.setState({
locations: result
});
}
});
},
})
},
}),
withScriptjs,
withGoogleMap
)(props =>
<GoogleMap>
<SearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
controlPosition={google.maps.ControlPosition.TOP_LEFT}
onPlacesChanged={props.onPlacesChanged}
>
<input
type="text"
placeholder="Customized your placeholder"
/>
</SearchBox>
{props.locations.map((location, index) => (
<span key={location._id.location.lng}>
<Marker
position={location._id.location}
onClick={() => props.onToggleOpen(index)}
/>
</span>
))}
</GoogleMap>
);

Resources