Skip to content

Fundamentals: No more flickering with render before activation global default option#1345

Open
torkelo wants to merge 25 commits intomainfrom
render-panel-before-activation
Open

Fundamentals: No more flickering with render before activation global default option#1345
torkelo wants to merge 25 commits intomainfrom
render-panel-before-activation

Conversation

@torkelo
Copy link
Collaborator

@torkelo torkelo commented Jan 30, 2026

Problems

  • Because scene components are not rendered until after the activation useEffect has triggered this "null" render clears the dom causing flickering when changing scene object instances
  • VizPanel does not render PanelChrome before div measurements are completed, causing minor flickering as PanelChrome is not rendered on first render
  • LazyLoader renders empty div before IntersectionObserver has checked if div is visible or not causing empty div on first render => flickering

Changes required when SceneObjectBase.RENDER_BEFORE_ACTIVATION_DEFAULT = true

  • Global static flag SceneObjectBase.RENDER_BEFORE_ACTIVATION_DEFAULT can now make all scene objects render before activation
  • This means panels/query runners activate before their parents, required change to isVariableLoadingOrWaitingToUpdate to account for sets that have not been activated yet
  • Scenes-react required changes, need to add the scene object to the context in the render path

Changes required for LazyLoader

  • We have to render children even on first mount, query execution is still blocked due to LazyLoaderInViewContext state which defaults to false
  • Question do we need an opt-in / option for this change in behavior?

Changes to VizPanelRendering

  • Render PanelChrome even when we have no div measurement (PanelChrome will be rendered with undefined width / height which will switch it to auto size mode).
  • Visualization is still not rendered until we have a measurement

To try the new mode, a scene app plugin or core Grafana can enable the new behavior by executing

  SceneObjectBase.RENDER_BEFORE_ACTIVATION_DEFAULT = true
render_before_activation.mp4

Related OSS PR: grafana/grafana#118567

📦 Published PR as canary version: 7.1.0--canary.1345.22579240520.0

✨ Test out this PR locally via:

npm install @grafana/scenes@7.1.0--canary.1345.22579240520.0
npm install @grafana/scenes-react@7.1.0--canary.1345.22579240520.0
# or 
yarn add @grafana/scenes@7.1.0--canary.1345.22579240520.0
yarn add @grafana/scenes-react@7.1.0--canary.1345.22579240520.0

@torkelo torkelo added minor Increment the minor version when merged release Create a release when this pr is merged labels Jan 30, 2026
@torkelo torkelo changed the title VizPanel: render before activation Fundamentals: Render before activation global default switch Feb 20, 2026
@torkelo torkelo changed the title Fundamentals: Render before activation global default switch Fundamentals: No more flickering with render before activation global default option Feb 20, 2026
@torkelo torkelo marked this pull request as ready for review February 20, 2026 11:53
this.runWithTimeRange(timeRange);
// setTimeout to let SceneVariableSet also respond to time range change
// So that variables that depend on time range have time to switch to loading state
setTimeout(() => this.runWithTimeRange(timeRange), 0);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This (and same in AnnotationDataLayer) is the only fix that trouble me but cannot figure out a fix without a much large system change.

The problem here is that SceneQueryRunner activates before any parent SceneVariableSet so SceneQueryRunner is first to subscribe to the time range so get's this event before SceneVariableSet so SceneVariableSet has no time to start loading a variable with refresh on time range change.

So, without this setTimeout, queries are executed twice if they depend on a variable that has "refresh on time range change".

to solve this more cleanly, we would need a new way to propagate time range changes from root to leaf (even React would struggle with this as useEffect triggers on leaves before children).

Copy link
Collaborator

@oscarkilhed oscarkilhed left a comment

Choose a reason for hiding this comment

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

I've tested this with Grafana and it seems to work just fine. Left some minor suggestions that were just typos.

torkelo and others added 6 commits March 2, 2026 12:30
Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Increment the minor version when merged release Create a release when this pr is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants