mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
parent
8d92417a16
commit
16f813fc04
@ -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;
|
||||||
|
}
|
||||||
|
@ -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: [
|
||||||
|
Loading…
Reference in New Issue
Block a user