Is there an existing issue for this?
Description of the bug
On iOS, the travelMode passed to setDestinations (in routingOptions or routeTokenOptions) is only applied to the GMSMapView of each NavigationView registered at that instant. It is never set on the GMSNavigationSession, whose navigator computes the route and whose travelMode defaults to driving.
When setDestinations runs before the NavigationView has attached to the session, the mode is lost and the route is computed as a driving route. This is the normal state for the first request after a launch in an app that mounts the NavigationView in the same React commit that starts guidance: the native view is created and registered, but attachToNavigationSessionIfNeeded only runs on its first non-zero layout, so the value set on the not-yet-attached map view never reaches the session.
Calling setDestinations again once the view is attached returns the correct route, which is why "change the travel mode and change it back" works around it.
Android is not affected: the mode travels inside RoutingOptions on every request.
iOS Platform
Android Platform
React Native version
0.86.3
React version
19.2.8
Package version
0.17.1 (the code is unchanged on main at 0.17.2)
Native SDK versions
iOS GoogleNavigation 11.1.0, Android navigation 7.9.0 (as pinned by the package)
Steps to reproduce
- Cold launch an app that renders a
MapView on its home screen and swaps it for a NavigationView when a destination is chosen, calling setDestinations(..., {routingOptions: {travelMode: TravelMode.CYCLING}}) from an effect in that same render.
- Call
startGuidance().
- Read
getCurrentTimeAndDistance() or look at the route.
- Change the travel mode and call
setDestinations again with the view now attached.
Expected vs Actual Behavior
Expected: the first route honours TravelMode.CYCLING.
Actual: the first route is a driving route. On a ~20 km test route (Montreal downtown to YUL, iPhone 17 Pro simulator, iOS 26.4) the first request returned 18.2 km in 46 min with delaySeverity: 2, which only driving routes carry; an explicit cycling request on the attached view returned 29.7 km in 96 min with delaySeverity: 0, and walking 18.6 km in 4 h 20. With the fix in the linked pull request the first request returns the 29.6 km / 96 min cycling route.
Code Sample
// Rendered as soon as a destination is chosen; NavigationView mounts in this same commit.
useEffect(() => {
if (!destination || !isNavigationInitialized) return;
navigationController.setDestinations([{title: destination.name, position: destination}], {
routingOptions: {travelMode: TravelMode.CYCLING, avoidHighways: true},
displayOptions: {showDestinationMarkers: true},
}).then(() => navigationController.startGuidance());
}, [destination, isNavigationInitialized]);
Additional Context
NavModule.mm configureNavigatorWithTravelMode: forwards to [NavViewModule setTravelMode:], which loops over viewControllersRegistry and calls [_mapView setTravelMode:]. GMSNavigationSession exposes its own travelMode property and it is never written. The fix is to set it there before updating the views, and to have a view that attaches later copy the session's mode.
Is there an existing issue for this?
Description of the bug
On iOS, the
travelModepassed tosetDestinations(inroutingOptionsorrouteTokenOptions) is only applied to theGMSMapViewof eachNavigationViewregistered at that instant. It is never set on theGMSNavigationSession, whose navigator computes the route and whosetravelModedefaults to driving.When
setDestinationsruns before theNavigationViewhas attached to the session, the mode is lost and the route is computed as a driving route. This is the normal state for the first request after a launch in an app that mounts theNavigationViewin the same React commit that starts guidance: the native view is created and registered, butattachToNavigationSessionIfNeededonly runs on its first non-zero layout, so the value set on the not-yet-attached map view never reaches the session.Calling
setDestinationsagain once the view is attached returns the correct route, which is why "change the travel mode and change it back" works around it.Android is not affected: the mode travels inside
RoutingOptionson every request.iOS Platform
Android Platform
React Native version
0.86.3
React version
19.2.8
Package version
0.17.1 (the code is unchanged on
mainat 0.17.2)Native SDK versions
iOS GoogleNavigation 11.1.0, Android navigation 7.9.0 (as pinned by the package)
Steps to reproduce
MapViewon its home screen and swaps it for aNavigationViewwhen a destination is chosen, callingsetDestinations(..., {routingOptions: {travelMode: TravelMode.CYCLING}})from an effect in that same render.startGuidance().getCurrentTimeAndDistance()or look at the route.setDestinationsagain with the view now attached.Expected vs Actual Behavior
Expected: the first route honours
TravelMode.CYCLING.Actual: the first route is a driving route. On a ~20 km test route (Montreal downtown to YUL, iPhone 17 Pro simulator, iOS 26.4) the first request returned 18.2 km in 46 min with
delaySeverity: 2, which only driving routes carry; an explicit cycling request on the attached view returned 29.7 km in 96 min withdelaySeverity: 0, and walking 18.6 km in 4 h 20. With the fix in the linked pull request the first request returns the 29.6 km / 96 min cycling route.Code Sample
Additional Context
NavModule.mmconfigureNavigatorWithTravelMode:forwards to[NavViewModule setTravelMode:], which loops overviewControllersRegistryand calls[_mapView setTravelMode:].GMSNavigationSessionexposes its owntravelModeproperty and it is never written. The fix is to set it there before updating the views, and to have a view that attaches later copy the session's mode.