Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ describe('ScopesVariable', () => {
const { valueChangedCount } = renderTestScene({ initialScopes: [] });
expect(valueChangedCount.value).toEqual(1);
});

it('should not emit a change event if the old and new scopes are empty', async () => {
const { scopesContext, valueChangedCount } = renderTestScene({ initialScopes: [] });

act(() => scopesContext.changeScopes([]));
act(() => scopesContext.changeScopes([]));

expect(valueChangedCount.value).toEqual(1);
});
});

interface SetupOptions {
Expand Down
6 changes: 5 additions & 1 deletion packages/scenes/src/variables/variants/ScopesVariable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export interface ScopesVariableState extends SceneVariableState {
export class ScopesVariable extends SceneObjectBase<ScopesVariableState> implements SceneVariable<ScopesVariableState> {
protected _renderBeforeActivation = true;
protected _context: ScopesContextValue | undefined;
// Used to always emit an update event on initial load
private _isInitialUpdate = true;

// Special options that enables variables to be hidden but still render to access react contexts
public UNSAFE_renderAsHidden = true;
Expand Down Expand Up @@ -100,11 +102,13 @@ export class ScopesVariable extends SceneObjectBase<ScopesVariableState> impleme
const scopesHaveChanged = !isEqual(oldScopes, newScopes);

// Only update scopes value state when loading is false and the scopes have changed
if (!loading && (scopesHaveChanged || newScopes.length === 0)) {
// Emit on initial load to ensure that the variable is updated when the scopes are empty
Copy link
Collaborator

Choose a reason for hiding this comment

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

Previously, this would cause a change event every time some url reloading would happen.

what do you mean by 'url reloading' ?

why would scopesHaveChanged be true and need to be ignored?

Copy link
Collaborator

@torkelo torkelo Sep 8, 2025

Choose a reason for hiding this comment

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

ah, is it the scenario where newScopes.length === 0?

hm... why is state updated with new empty scopes array on every url update?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was noticed when switching on/off edit mode in dashboards, with empty set of scopes. I would assume that the URL change it causes also makes the scopes update?

Regardless, I think newScopes.length === 0 is weird check that doesn't really do what it is supposed to. scopesHaveChanged is not true for the initial load.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@tskarhed but why is stateObservable emitting a new scope value when going into/out of edit mode?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@torkelo apparently this only happens when no scope is selected. @tskarhed is there any special handling for such case with empty scopes? I don't understand why this problem only occurs with scopes being empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tskarhed but why is stateObservable emitting a new scope value when going into/out of edit mode?

I'll see if I can look further into it next week.

@torkelo apparently this only happens when no scope is selected. @tskarhed is there any special handling for such case with empty scopes? I don't understand why this problem only occurs with scopes being empty.

Do you mean the emitting of stateObservable when there is no reason to?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you mean the emitting of stateObservable when there is no reason to?

yes, exactly

if (!loading && (scopesHaveChanged || this._isInitialUpdate)) {
const queryController = getQueryController(this);
queryController?.startProfile(SCOPES_CHANGED_INTERACTION);
this.setState({ scopes: state.value, loading });
this.publishEvent(new SceneVariableValueChangedEvent(this), true);
this._isInitialUpdate = false;
} else {
this.setState({ loading });
}
Expand Down