Saturday, June 1, 2024
 Popular · Latest · Hot · Upcoming
84
rated 0 times [  85] [ 1]  / answers: 1 / hits: 20678  / 7 Years ago, sun, september 17, 2017, 12:00:00

I have a pretty simple react application using https://github.com/tomchentw/react-google-maps but I'm having difficulty understanding how to get a reference to my current map or how to access the google.maps.Map object in a custom component.


I found this on the repo, but after reading through the posts I'm still a little confused.


I'm starting my application building off of the DirectionsRenderer example.


What I want to do next is add my own custom components for picking the starting point and using the Google Maps autocomplete API.



Yes, I know that the package has a component for that already, but I
need to do a little more than just search for a location on the map.



In order to accomplish my needs I will do something like


const autocomplete = new google.maps.places.Autocomplete(node);
autocomplete.bindTo('bounds', map);

Where node is the element I'm binding the autocomplete functionality and map is an instance of the google.maps.Map object.


My application thus far:


App.jsx


const App = ({ store }) => (
<Provider store={store}>
<div>
<Sidebar>
<StartingPoint defaultText="Choose starting point&hellip;" />
</Sidebar>
<GoogleApiWrapper />
</div>
</Provider>
);

GoogleApiWrapper


const GoogleMapHOC = compose(
withProps({
googleMapURL: 'https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=__GAPI_KEY',
loadingElement: <div style={{ height: '100vw' }} />,
containerElement: <div style={{ height: '100vh' }} />,
mapElement: <div style={{ height: '100%' }} />,
}),
withScriptjs,
withGoogleMap,
lifecycle({
componentDidMount() {
const DirectionsService = new google.maps.DirectionsService();

// make google object available to other components
this.props.onLoad(google);

DirectionsService.route({
origin: new google.maps.LatLng(41.8507300, -87.6512600),
destination: new google.maps.LatLng(41.8525800, -87.6514100),
travelMode: google.maps.TravelMode.DRIVING,
}, (result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.setState({
directions: result,
});
} else {
console.error(`error fetching directions ${result}`);
}
});
},
}),
)(props => (
<GoogleMap
ref={props.onMapMounted}
defaultZoom={13}
defaultCenter={new google.maps.LatLng(37.771336, -122.446615)}
>
{props.directions && <DirectionsRenderer directions={props.directions} />}
</GoogleMap>
));

If I'm unable to access the google.maps.Map object outside of the wrapper I would alternatively like to access a reference to the element that contains the map so that I may instantiate a new google.maps.Map(ref_to_elem, options);


Any help would be greatly appreciated!


More From » reactjs

 Answers
8

After thoroughly reading through the react-google-maps documentation, examples, and issues I have come to learn that the package does not support a lot of the things I will need to do for my application.



That being said, I have begun writing my own Google Maps API wrapper based off of the work done by Fullstack React. I've omitted a lot of the utilities used in the below mentioned as they can be found here or here.



That being said my solution is to wrap the google maps container in a higher order component and expose the Map Object via the window object:



App



const App = ({ store }) => (
<Provider store={store}>
<div>
<Sidebar>
<StartingPoint />
{/* TODO */}
</Sidebar>
<GoogleMap />
</div>
</Provider>
);


containers/GoogleMap/wrapper.jsx Google Map Higher Order Component wraps GoogleMap Container



const defaultCreateCache = (options) => {
const opts = options || {};
const apiKey = opts.apiKey;
const libraries = opts.libraries || ['places'];
const version = opts.version || '3.24';
const language = opts.language || 'en';

return ScriptCache({
google: GoogleApi({
apiKey,
language,
libraries,
version,
}),
});
};

const wrapper = options => (WrappedComponent) => {
const createCache = options.createCache || defaultCreateCache;

class Wrapper extends Component {
constructor(props, context) {
super(props, context);

this.scriptCache = createCache(options);
this.scriptCache.google.onLoad(this.onLoad.bind(this));

this.state = {
loaded: false,
google: null,
};
}

onLoad() {
this.GAPI = window.google;

this.setState({ loaded: true, google: this.GAPI });
}

render() {
const props = Object.assign({}, this.props, {
loaded: this.state.loaded,
google: window.google,
});
const mapRef = (el) => { this.map = el; };

return (
<div>
<WrappedComponent {...props} />
<div ref={mapRef} />
</div>
);
}
}
Wrapper.propTypes = {
dispatchGoogleAPI: PropTypes.func,
};
Wrapper.defaultProps = {
dispatchGoogleAPI: null,
};

return Wrapper;
};

export default wrapper;


containers/GoogleMap/index.jsx Google Map Container



class Container extends Component {
constructor(props) {
super(props);

this.loadMap = this.loadMap.bind(this);
this.calcRoute = this.calcRoute.bind(this);
}

componentDidUpdate() {
const { origin, destination, route } = this.props;

this.calcRoute(origin, destination);
}

loadMap(node) {
if (this.props && this.props.google) {
const { google } = this.props;

// instantiate Direction Service
this.directionsService = new google.maps.DirectionsService();

this.directionsDisplay = new google.maps.DirectionsRenderer({
suppressMarkers: true,
});

const zoom = 13;
const mapTypeId = google.maps.MapTypeId.ROADMAP;
const lat = 37.776443;
const lng = -122.451978;
const center = new google.maps.LatLng(lat, lng);

const mapConfig = Object.assign({}, {
center,
zoom,
mapTypeId,
});

this.map = new google.maps.Map(node, mapConfig);

this.directionsDisplay.setMap(this.map);

// make the map instance available to other components
window.map = this.map
}
}

calcRoute(origin, destination) {
const { google, route } = this.props;

if (!origin && !destination && !route) return;

const waypts = [];

waypts.push({
location: new google.maps.LatLng(37.415284, -122.076899),
stopover: true,
});

const start = new google.maps.LatLng(origin.lat, origin.lng);
const end = new google.maps.LatLng(destination.lat, destination.lng);

this.createMarker(end);

const request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: true,
travelMode: google.maps.DirectionsTravelMode.DRIVING,
};

this.directionsService.route(request, (response, status) => {
if (status === google.maps.DirectionsStatus.OK) {
this.directionsDisplay.setDirections(response);
const route = response.routes[0];
console.log(route);
}
});

this.props.calculateRoute(false);
}

createMarker(latlng) {
const { google } = this.props;

const marker = new google.maps.Marker({
position: latlng,
map: this.map,
});
}

render() {
return (
<div>
<GoogleMapView loaded={this.props.loaded} loadMap={this.loadMap} />
</div>
);
}
}

const GoogleMapContainer = wrapper({
apiKey: ('YOUR_API_KEY'),
version: '3', // 3.*
libraries: ['places'],
})(Container);

const mapStateToProps = state => ({
origin: state.Trip.origin,
destination: state.Trip.destination,
route: state.Trip.route,
});

const mapDispatchToProps = dispatch => ({
dispatchGoogleMap: (map) => {
dispatch(googleMap(map));
},
calculateRoute: (route) => {
dispatch(tripCalculation(route));
},
});

const GoogleMap = connect(mapStateToProps, mapDispatchToProps)(GoogleMapContainer);

export default GoogleMap;

[#56457] Thursday, September 14, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
madelyn

Total Points: 449
Total Questions: 100
Total Answers: 100

Location: Seychelles
Member since Fri, May 7, 2021
3 Years ago
madelyn questions
Wed, Jul 28, 21, 00:00, 3 Years ago
Wed, Jul 14, 21, 00:00, 3 Years ago
Sat, Nov 7, 20, 00:00, 4 Years ago
Thu, Sep 3, 20, 00:00, 4 Years ago
;