Skip to content

feat(core): Add Deck#getView() method#9948

Merged
chrisgervang merged 3 commits intomasterfrom
chrisgervang/viewport-from-map
Feb 2, 2026
Merged

feat(core): Add Deck#getView() method#9948
chrisgervang merged 3 commits intomasterfrom
chrisgervang/viewport-from-map

Conversation

@chrisgervang
Copy link
Collaborator

@chrisgervang chrisgervang commented Jan 20, 2026

Closes #9709

Summary

  • Adds a public Deck#getView(viewId) method that returns a View by its id
  • Updates getViewport in @deck.gl/mapbox deck-utils to use the new API instead of manually searching through deck.props.views
  • Adds tests for single view and multiple views cases

This extracts the view lookup logic that was previously duplicated, making it a proper part of the Deck public API.

Test plan

  • TypeScript compilation passes for modules/core and modules/mapbox
  • Unit tests pass (Deck#getView with single view, Deck#getView with multiple views)
  • Manual testing with MapboxOverlay

🤖 Generated with Claude Code


Note

Low Risk
Small, additive API change with limited refactor in mapbox viewport selection; risk is mainly incorrect view resolution/regressions in mapbox overlays.

Overview
Adds a public view lookup API. Deck now exposes getView(viewId) (in addition to getViews) and documents it in the API reference.

@deck.gl/mapbox switches its viewport creation logic to use deck.getView('mapbox') instead of manually searching deck.props.views, and reorders isInitialized guards to exit earlier in drawLayer/drawLayerGroup. New unit tests cover getView for single and multiple view configurations.

Written by Cursor Bugbot for commit ba3a9b9. This will update automatically on new commits. Configure here.

const viewState = getViewState(map);
const {views} = deck.props;
const view =
(views && flatten(views).find((v: {id: string}) => v.id === MAPBOX_VIEW_ID)) ||
Copy link
Collaborator Author

@chrisgervang chrisgervang Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the use of flatten was odd since I can't think of a case where you'd have nested arrays of views.. the type is

// view-manager.ts:18
export type ViewOrViews = View | View[] | null;

But, looks like ViewManager is likely just being defensive, or its an old pattern?

// view-manager.ts:268-269
private _setViews(views: View[]): void {
  views = flatten(views, Boolean); // why are views flattened?
  ...
}

Either way, calling deck.getView() maintains the same behavior since view manager already normalized the list.

@chrisgervang chrisgervang force-pushed the chrisgervang/viewport-from-map branch from aecfd6a to 345dc2a Compare January 20, 2026 23:05
@coveralls
Copy link

coveralls commented Jan 20, 2026

Coverage Status

coverage: 91.09% (+0.001%) from 91.089%
when pulling ba3a9b9 on chrisgervang/viewport-from-map
into 6149b4c on master.

const view =
(views && flatten(views).find((v: {id: string}) => v.id === MAPBOX_VIEW_ID)) ||
getDefaultView(map);
const view = (deck.isInitialized && deck.getView(MAPBOX_VIEW_ID)) || getDefaultView(map);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is adding isInitialized a change in behavior?

Copy link
Collaborator Author

@chrisgervang chrisgervang Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't be. That guards against assert(this.viewManager) in deck.getView(), and the fallback returns the same view that would have been found anyway unless a user is supplying their own custom view with the id mapbox.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, actually digging in more to the custom view case, claude laid out a subtle behavior change:

Let me trace through the custom view scenario:

Original code:

const view = (views && flatten(views).find(...)) || getDefaultView(map);

Before initialization, this searches deck.props.views and WOULD find the user's custom view.

New code:

const view = ((deck.isInitialized && deck.getView(MAPBOX_VIEW_ID)) || getDefaultView(map))

Before initialization, this falls back to getDefaultView(map) - NOT the user's custom view.

So yes, there's a subtle difference: if a user provides a custom view with id 'mapbox', and the map renders before deck initializes, the cached viewport would be created from the default view instead of their custom view.

However:

  • This window is very brief (one frame at most)
  • afterRender clears the cache once deck initializes
  • Subsequent frames use the correct custom view

We could preserve the original behavior by adding a fallback search of deck.props.views:

const view = (deck.isInitialized && deck.getView(MAPBOX_VIEW_ID)) ||
  deck.props.views?.find?.(v => v.id === MAPBOX_VIEW_ID) ||
  getDefaultView(map);

We could move the deck.isInitialized guard in drawLayer to the top, and then remove the guard within getViewport altogether. I pushed a commit with this change - It seems cleaner to do nothing until deck is initialized

@chrisgervang chrisgervang force-pushed the chrisgervang/viewport-from-map branch from 345dc2a to 177393f Compare January 27, 2026 05:15
chrisgervang and others added 2 commits January 26, 2026 21:59
Add a public `getView(viewId)` method to the Deck class that returns
a View by its id. This extracts the view lookup logic that was previously
duplicated in places like MapboxOverlay's deck-utils.

- Add `Deck#getView(viewId: string): View | undefined`
- Update `getViewport` in deck-utils to use the new API
- Add tests for single view and multiple views cases

Closes #9709

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This ensures getViewport is only called when deck is initialized,
which allows us to simplify getViewport by removing the redundant
isInitialized check. The fallback to getDefaultView remains for
safety but deck.getView() will now always find the configured view.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chrisgervang chrisgervang force-pushed the chrisgervang/viewport-from-map branch from 73cb4e9 to 12a9e04 Compare January 27, 2026 05:59
@chrisgervang
Copy link
Collaborator Author

chrisgervang commented Feb 2, 2026

I've tested on basemap-browser and website examples. All looks good!

@chrisgervang chrisgervang mentioned this pull request Feb 2, 2026
12 tasks
@chrisgervang chrisgervang merged commit 1cd8eea into master Feb 2, 2026
6 checks passed
@chrisgervang chrisgervang deleted the chrisgervang/viewport-from-map branch February 2, 2026 23:42
@chrisgervang chrisgervang added this to the v9.3 milestone Feb 2, 2026
felixpalmer pushed a commit that referenced this pull request Feb 10, 2026
* feat(core): Add Deck#getView() method

Add a public `getView(viewId)` method to the Deck class that returns
a View by its id. This extracts the view lookup logic that was previously
duplicated in places like MapboxOverlay's deck-utils.

- Add `Deck#getView(viewId: string): View | undefined`
- Update `getViewport` in deck-utils to use the new API
- Add tests for single view and multiple views cases

Closes #9709

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor(mapbox): Move isInitialized check to top of draw functions

This ensures getViewport is only called when deck is initialized,
which allows us to simplify getViewport by removing the redundant
isInitialized check. The fallback to getDefaultView remains for
safety but deck.getView() will now always find the configured view.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Deck#getView()

3 participants