I am trying to display route between two points on leaflet map. For that purpose I am using leaflet-routing-machine. But I have problem with passing map object to leaflet route component.
map_container.js
...
return (
<Map ref='map' center={position} zoom={this.state.zoom}>
<TileLayer
attribution="&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Routing map={this.refs.map} from={[51.599684, 15.27539]} to={[51.602292, 15.295128]} />
</Map>
)
...
routing.js
import {MapLayer} from 'react-leaflet';
import L from 'leaflet';
import 'leaflet-routing-machine';
export default class RoutingMachine extends MapLayer {
componentWillMount() {
super.componentWillMount();
this.leafletElement.addTo(this.props.map);
}
render() {
return null;
}
createLeafletElement (props) {
const {from, to} = this.props;
console.log(this.props)
var leafletElement = L.Routing.control({
waypoints: [
L.latLng(from[0], from[1]),
L.latLng(to[0], to[1]),
],
});
return leafletElement;
}
}
Errors I get:
{map: undefined, from: Array(2), to: Array(2)}
bundle.js:69506 Uncaught TypeError: Cannot read property 'getSize' of undefined
at NewClass.onAdd (bundle.js:69506)
at NewClass.onAdd (bundle.js:68679)
at NewClass.addTo (bundle.js:26718)
But what is most interesting - everything does work perfectly on "react-leaflet": "1.1.0" version, but on 1.1.1 and above it breaks.
Any ideas?
Okey, after a while I've found a solution. Cannot read property 'getSize' of undefined error was caused by map passed to refs only after whole module has loaded. It can be fixed by adding:
return ( this.map ?
<Map onClick={(e) => this._mapClickEvent(e)} className="main-screen-map-container" center={position}
zoom={this.state.zoom} ref={map => this.map = map}>
<TileLayer
attribution="&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Routing map={this._getMap()} from={[11.11, 12.12]} to={[11.11, 12.12]}
by={this.props.busstops}/>
</Map>
:
<Map onClick={(e) => this._mapClickEvent(e)} className="main-screen-map-container" center={position}
zoom={this.state.zoom} ref={map => this.map = map}>
<TileLayer
attribution="&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</Map>
Which checks if map is already defined, then rerenders it with road on it. Depending on the rest of your code (if you are fetching some data using Redux and setting state which forces update) it may be required to also add following code:
componentDidMount() {
console.log("map did mount " + this.map);
this.forceUpdate()
}
That should fix it. PS ternary operator could also be refactored by removing redundant code and just adding
_addRouting() {
if (this.map) {
return (
<div>
<Routing map={this._getMap()} from={[11.11, 12.12]} to={[11.11, 12.12]}
by={this.props.busstops}/>
</div>
)
}
}
and then injecting it in render method.
Still have no idea why this problem didn't occur on older versions of react-leaflet.