fix: fly_to in overlay/interleaved basemap mode#1123
fix: fly_to in overlay/interleaved basemap mode#1123tylere wants to merge 4 commits intodevelopmentseed:mainfrom
Conversation
The OverlayRenderer passes initialViewState to react-map-gl's <MapGL>, which only reads that prop on mount and ignores subsequent updates. This meant fly_to() calls from Python had no visible effect when using overlaid or interleaved basemap modes. Fix by using a MapGL ref to call MapLibre's native map.flyTo() API directly when a fly-to request arrives, while keeping the existing uncontrolled view state management unchanged for normal pan/zoom. Also filter out transition_* fields from view state dicts sent by the frontend before constructing Python ViewState dataclasses, preventing TypeError on unexpected keyword arguments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Fixes #1064. |
There was a problem hiding this comment.
Pull request overview
Fixes fly_to() not animating the map when using the default basemap modes (“overlaid” / “interleaved”) by routing fly-to requests through MapLibre’s native map.flyTo() in the overlay renderer, and hardens Python view state validation against frontend transition* fields.
Changes:
- Add
flyToRequestplumbing to the overlay renderer and invokemap.flyTo()via aMapGLref. - Route
"fly-to"custom messages to the overlay renderer in overlaid/interleaved basemap modes; keep existing deck-first behavior. - Filter out
transition*keys from frontend-sent view state dicts before constructing PythonViewStatedataclasses.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/renderers/types.ts | Extends overlay renderer prop types to accept a fly-to request and completion callback. |
| src/renderers/overlay.tsx | Uses a MapGL ref + effect to call MapLibre flyTo() in overlay mode. |
| src/index.tsx | Stores fly-to requests in React state for overlay/interleaved modes and passes them to OverlayRenderer. |
| lonboard/traits/_map.py | Drops transition* fields from view state dict inputs to avoid dataclass constructor errors. |
Comments suppressed due to low confidence (1)
src/index.tsx:183
model.on("msg:custom", ...)is being called during render, which will register a new event handler on every re-render and can cause duplicated fly-to handling and memory leaks. Move this subscription into auseEffectwith a stable handler and cleanup viamodel.off("msg:custom", handler)in the effect's return function.
// Handle custom messages
model.on("msg:custom", (msg: Message) => {
switch (msg.type) {
case "fly-to":
if (
basemapState?.mode === "overlaid" ||
basemapState?.mode === "interleaved"
) {
setFlyToRequest(msg);
} else {
flyTo(msg, setViewState);
}
break;
default:
break;
}
});
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ...deckProps | ||
| } = mapProps; | ||
|
|
||
| const mapRef = React.useRef<MapRef>(null); |
There was a problem hiding this comment.
React.useRef<MapRef>(null) is a TypeScript error under strictNullChecks because the initial value is null but the ref type is non-nullable. Make the ref type nullable (e.g., MapRef | null) or omit the explicit generic so the inferred type matches the null initializer.
| const mapRef = React.useRef<MapRef>(null); | |
| const mapRef = React.useRef<MapRef | null>(null); |
| # Filter out transition fields that are not part of the view state dataclass | ||
| snake_case_kwargs = { | ||
| k: v for k, v in snake_case_kwargs.items() if not k.startswith("transition") | ||
| } |
There was a problem hiding this comment.
This new filtering of transition* keys should be covered by a unit test to prevent regressions (e.g., ensure a camelCase transitionDuration/transitionInterpolator key in an incoming view_state dict is ignored rather than raising TypeError). There are already view_state validation tests in tests/test_map.py that could be extended for this case.
Summary
fly_to()having no effect when the basemap mode is "overlaid" or "interleaved" (the default). TheOverlayRendererpassesinitialViewStateto react-map-gl's<MapGL>, which only reads that prop on initial mount and ignores subsequent updates.MapGLref to call MapLibre's nativemap.flyTo()API directly when a fly-to request arrives, keeping the existing uncontrolled view state management unchanged for normal pan/zoom.transition_*fields from view state dicts sent by the frontend before constructing PythonViewStatedataclasses, preventingTypeErroron unexpected keyword arguments liketransition_duration.Test plan
npm run buildcompletes without errorsm = viz(gdf)thenm.fly_to(longitude=..., latitude=..., zoom=...)— verify the map animatesm = Map(layers=[...])thenm.fly_to(...)🤖 Generated with Claude Code