Scene: Fixing state issue with useState when SceneObject instance changes (#52372)

* ScenePanelRepeater: Fixes refreshes temporarily by setting key to guid

* Fixing issue with old state being returned by useState when the scene object instance changed (with same react key)
This commit is contained in:
Torkel Ödegaard 2022-07-19 17:47:59 +02:00 committed by GitHub
parent 8d92417a16
commit 16f813fc04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 4 deletions

View File

@ -1,8 +1,9 @@
import { useObservable } from 'react-use'; import { useEffect } from 'react';
import { Observer, Subject, Subscription } from 'rxjs'; import { Observer, Subject, Subscription } from 'rxjs';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { EventBusSrv } from '@grafana/data'; import { EventBusSrv } from '@grafana/data';
import { useForceUpdate } from '@grafana/ui';
import { SceneComponentWrapper } from './SceneComponentWrapper'; import { SceneComponentWrapper } from './SceneComponentWrapper';
import { SceneObjectStateChangedEvent } from './events'; import { SceneObjectStateChangedEvent } from './events';
@ -118,7 +119,7 @@ export abstract class SceneObjectBase<TState extends SceneObjectState = {}> impl
useState() { useState() {
// eslint-disable-next-line react-hooks/rules-of-hooks // eslint-disable-next-line react-hooks/rules-of-hooks
return useObservable(this.subject, this.state); return useSceneObjectState(this);
} }
/** /**
@ -197,3 +198,18 @@ export abstract class SceneObjectBase<TState extends SceneObjectState = {}> impl
return new (this.constructor as any)(clonedState); return new (this.constructor as any)(clonedState);
} }
} }
/**
* This hook is always returning model.state instead of a useState that remembers the last state emitted on the subject
* The reason for this is so that if the model instance change this function will always return the latest state.
*/
function useSceneObjectState<TState>(model: SceneObjectBase<TState>): TState {
const forceUpdate = useForceUpdate();
useEffect(() => {
const s = model.subject.subscribe(forceUpdate);
return () => s.unsubscribe();
}, [model, forceUpdate]);
return model.state;
}

View File

@ -78,7 +78,7 @@ export function getScenePanelRepeaterTest(): Scene {
uid: 'gdev-testdata', uid: 'gdev-testdata',
type: 'testdata', type: 'testdata',
}, },
seriesCount: 5, seriesCount: 2,
alias: '__server_names', alias: '__server_names',
scenarioId: 'random_walk', scenarioId: 'random_walk',
}, },
@ -119,7 +119,7 @@ export function getScenePanelRepeaterTest(): Scene {
$data: queryRunner, $data: queryRunner,
actions: [ actions: [
new SceneToolbarInput({ new SceneToolbarInput({
value: '5', value: '2',
onChange: (newValue) => { onChange: (newValue) => {
queryRunner.setState({ queryRunner.setState({
queries: [ queries: [