[Bug] Controlled viewport does not restore rejected movement
Author: km-git007Created Jul 17, 2026Updated Jul 17, 2026
Reproduction
const lockedViewport: MapViewport = {
center: [2.3522, 48.8566],
zoom: 10,
bearing: 0,
pitch: 0,
};
<Map
viewport={lockedViewport}
onViewportChange={() => {
// Intentionally reject the proposed user movement.
}}
/>- Drag or zoom the map.
- Release the gesture.
Actual behavior
The map remains at the user-moved viewport even though the controlled prop never changed.
Expected behavior
The controlled fields return to the values in viewport after the gesture ends.
Cause
The prop-sync effect returns while map.isMoving() is true. Because the parent retained the same prop object/value, the effect has no dependency change after moveend, so it never reconciles the rejected movement.
Proposed compatibility contract
viewport+onViewportChange: fields present inviewportare authoritative.onViewportChangealone: observer-only mode remains unchanged.viewportalone: initial-value behavior remains unchanged.- Omitted fields remain independently uncontrolled.
- Rejected movement reconciles on
moveend. - A new conflicting authoritative prop during movement stops movement and applies immediately.
I can send a focused fix with no dependency or public prop additions. If this contract matches your intent, please assign the issue to km-git007 or comment exactly approved for implementation.
Source: AnmolSaini16/mapcn