@alex3165
I'm currently using the map.flyTo inside the
onStyleLoad={map => {
}}
It's working fine but, the flyTo happens at the initial render
my goal is to update the map.flyTo options dynamically on button Click?
how can I achieve that?
is the map.flyTo provided as a prop?
here's my current code:
constructor(props) {
super(props);
this.state = {
flyTo: { center: [-118.4107187, 33.9415889], zoom: 11, speed: 0.4 }
}
...
...
handleClickFlyDestinationAirport = () => {
this.setState({ flyTo: { center: [-122.404357, 37.791246], zoom: 11, speed: 0.4 } })
}
<Map
style="mapbox://styles/myAccount/vfvjiej45de7k"
center={this.state.start}
zoom={[9.8]}
movingMethod="flyTo"
containerStyle={{
height: '100vh',
width: '100vw'
}}
onStyleLoad={map => {
map.addLayer({
id: 'routes',
type: 'line',
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
'features': [{
type: 'Feature',
properties: {
'color': 'blue',
},
geometry: this.state.geoJsonData1
}, {
type: 'Feature',
properties: {
'color': '#FF793F',
},
geometry: {
"type": "LineString",
"coordinates": [
this.state.start2,
this.state.destination2
]
}
}, {
type: 'Feature',
properties: {
'color': 'green',
},
geometry: this.state.geoJsonData2
}]
}
},
paint: {
'line-width': 3,
'line-color': {
'type': 'identity',
'property': 'color'
}
}
}),
map.flyTo(this.state.flyTo);
}}
/>
<button className={css(styles.flyToButtonMap)} onClick={this.handleClickFlyDestinationAirport}>Fly to the dest Airport</button>

You could get a reference to your map by adding <Map ref={(e) => { this.map = e; }} />. After that you've got this.map available which you could set as a prop or state. You can call flyTo and any other method on it!
@aderaaij I got a reference to my map by following your advice, then I added it to the state in componentDidMount by doing this.setState({ mapRef: this.map }).
but how can I call the flyTomethod from within my clickHandler function ?
You don鈥檛 need to put refs in the state. It鈥檚 fine to read them from the instance where you already store it. In the click handler, you can call this.map.flyTo(), can you not?
@gaearon
Well when I use
handleClickFlyDestinationAirport = () => {
this.map.flyTo({ center: [-118.4107187, 33.9415889] })
}
I get an Uncaught TypeError: _this.map.flyTo is not a function
HelpPage.js:81 Uncaught TypeError: _this.map.flyTo is not a function
at HelpPage._this.handleClickFlyDestinationAirport (HelpPage.js:81)
at HTMLUnknownElement.callCallback (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17388)
at Object.invokeGuardedCallbackDev (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17427)
at Object.invokeGuardedCallback (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17284)
at Object.invokeGuardedCallbackAndCatchFirstError (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17298)
at executeDispatch (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17682)
at executeDispatchesInOrder (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17704)
at executeDispatchesAndRelease (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17802)
at executeDispatchesAndReleaseTopLevel (modules.js?hash=04ceea1cc27f31ca61574df316b23853ebac8f98:17813)
at Array.forEach (<anonymous>)
@aziz-boudi4 The actual map object is not this.map, the ref you get is a ref to the React component, not to the map itself. You can find the map in this.map.state.map. Just console.log this.map and you'll see what's available!
@aderaaij yes Arden, It's indeed working when I use this.map.state.map. I didn't try that because when I consoled logged earlier the method flyTo was not there.
quick question though, just to fully understand:
1- how come the this.map has a state.map ? can you please elaborate on that?
and thank you again for your help and guidance.
@aziz-boudi4 glad to hear it's working. When you get your ref to the map, it actually refers to the ReactMapboxGL component, which is a React component and not the map itself. The ReactMapboxGL component has the actual mapboxgl map in its state on which we can apply the normal mapbox API. To be honest, I'm not sure if this is the best way to get a reference to the map but I had the same problem as you and this seems to work fine for me!
@gaearon wow you're everywhere 馃檶 (was really enjoying your React thread on dev.to). Anyhow, I also pass the reference from the map to the state because I pass it as prop to a child component. As the ref is undefined until the component is mounted, I add it to state in componentDidMount. Would there be a better way to do this?
@aderaaij great, well it's working for me as well.
maybe @alex3165 or @gaearon can tell us if there's a better way to do that ?
@aziz-boudi4 : I actually show an example of this exact idea in my post Declaratively Rendering Earth in 3D, Part 2: Controlling Cesium with React. I'd encourage you to read through that post. Your specific question is covered in the section where I talk about updating the camera position based on state changes.
Hey @aziz-boudi4, sorry for the late reply, thanks everyone for helping out on this issue. I would rather avoid calling map.flyTo manually, you can play with center and zoom props of the map component to achieve what you want to do (and keep center and zoom in your state). The purpose of the library is to abstract those manual calls to mapbox API so that it is more declarative.
Also instead of calling map.addLayer you can use the GeoJsonLayer component https://github.com/alex3165/react-mapbox-gl/blob/master/example/src/demos/geojsonLayer.tsx or you could even use Layer and Feature to render a line, see the allShapes example: https://github.com/alex3165/react-mapbox-gl/blob/master/example/src/demos/allShapes.tsx
@alex3165 thank you for the info Alex, oh you mean putting Center and Zoom on the state and updating them when the user clicks on a specific button? can I do the same thing for Bearing and Pitch which are options of the flyTo method?
Thank you, I will have a look at the examples you gave me, and try to use GeoJsonLayer
Just to make sure we're clear, it's a bad idea to read .state. of another component. State is typically considered private.
I'm finding it hard to understand what you're asking. If you created a tiny mockup with a fake map component just to illustrate the issue that would help.
I think the "mistake" here is the way you look at flyto. You should think of flyTo not as a method of changing the center point or other properties of the map, but an animation method to move the camera. As soon as you need to use interactions to move the map it's important to grasp the concept of the camera being your view into the map.
So if you want to fly somewhere, in reality what you essentially want is to update position, bearing, zoom etc and move from current state to next state with a flyto animation type. And there's many ways to do that. Fit bounds is one, depends a bit what you are trying to do. Looks like you can get away with just updating position though.
Does anyone here know how you would center the map on a custom ShapeSource icon on click? The icon gets its coordinate from GeoJson. I've tried the following inside Shapesource, but it just takes me to the first location (not the icon's coordinates).
onPress={() => {this.map.flyTo(featureCollection.features[0].geometry.coordinates, 1000);}}
Most helpful comment
@aziz-boudi4 The actual map object is not
this.map, the ref you get is a ref to the React component, not to the map itself. You can find the map inthis.map.state.map. Justconsole.logthis.mapand you'll see what's available!