Sorry in advance for the long code sample. I'm making an API call(Mapbox Directions API) in my componentDidMount to get coordinates points and draw an itinerary line between multiple coordinates. I'm currently drawing a line on my map based on coordinates I get from this API call, the thing is, the API call is made based on data stored in my Redux store, if I change the store, the line drawn on the map stays there (because componentDidMount is not called again, so the data for the line stays the same). I'm no React expert and I'm looking for an elegant way to refresh line drawn on the map. Any help is appreciated ! Thanks in advance.
Dave
import React, { Component } from 'react';
import ReactMapboxGl, { Marker } from 'react-mapbox-gl';
import marker from '../../assets/images/marker.png';
import Loading from '../Loading';
import { connect } from 'react-redux';
import ItineraryCard from '../Itinerary/ItineraryCard';
import photo1 from '../../assets/images/nav_tourisme.jpg';
const Map = ReactMapboxGl({
accessToken:
'...',
});
class MapWithLine extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
data: [],
isLoaded: false,
zoom: [13],
};
}
onMapLoad = map => {
map.addLayer({
id: 'route',
type: 'line',
source: {
type: 'geojson',
data: {
type: 'Feature',
properties: {},
geometry: {
type: 'LineString',
coordinates: this.state.data,
},
},
},
layout: {
'line-join': 'round',
'line-cap': 'round',
},
paint: {
'line-color': '#888',
'line-width': 8,
},
});
map.resize();
};
removeLastCharacter(str) {
if (str != null && str.length > 0) {
str = str.substring(0, str.length - 1);
}
return str;
}
getItineraryCoords() {
let itineraryString = '';
this.props.itineraryReducer.itinerary.map(exp => {
const coords = exp.lng + ',' + exp.lat + ';';
itineraryString = itineraryString + coords;
return itineraryString;
});
return this.removeLastCharacter(itineraryString);
}
componentDidMount() {
if (this.props.itineraryReducer.itinerary.length > 1) {
const url =
'https://api.mapbox.com/directions/v5/mapbox/' +
'driving/' +
this.getItineraryCoords() +
'?geometries=geojson&' +
'access_token='...';
fetch(url)
.then(response => response.json())
.then(
result => {
result.routes
? this.setState({
data: result.routes[0].geometry.coordinates,
isLoaded: true,
})
: this.setState({
isLoaded: true,
});
},
error => {
this.setState({
isLoaded: true,
error: error,
});
}
);
}
}
componentWillUnmount() {
//Resume scrolling on body when drawer is not maximized (component unmounted)
document.body.style.overflow = 'visible';
}
render() {
const { error, isLoaded } = this.state;
if (error) {
return <div>Error: {error.message}</div>;
} else if (!isLoaded) {
return <Loading />;
} else {
return (
<div className="mapWrapper">
<Map
style="mapbox://styles/mapbox/streets-v8"
className="mapContainer"
center={this.state.data[0]}
zoom={this.state.zoom}
onStyleLoad={this.onMapLoad}
>
});
{this.props.itineraryReducer.itinerary.map((exp, index) => {
const coords = [exp.lng, exp.lat];
return (
<Marker coordinates={coords} anchor="bottom" key={index}>
<img src={marker} alt="marker-icon" className="mapMarker" />
</Marker>
);
})}
</Map>
</div>
);
}
}
}
const mapStateToProps = state => {
return {
itineraryReducer: state.itineraryReducer,
};
};
export default connect(mapStateToProps)(MapWithLine);