grafana/public/app/features/dashboard/components/PanelEditor/usePanelLatestData.ts
Ryan McKinley dff78561bc
PanelData: include structure revision info and only apply overrides once (#33098)
* calculate schemaRevision in panel query runner

* schema > structureRev

* calculate revision after apply field overrides

* this.state

* don't apply field overrides if the shape is already the same

* check schema revision

* update snapshots
2021-04-20 11:05:50 +02:00

68 lines
2.0 KiB
TypeScript

import { DataQueryError, LoadingState, PanelData } from '@grafana/data';
import { useEffect, useRef, useState } from 'react';
import { PanelModel } from '../../state';
import { Unsubscribable } from 'rxjs';
import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
interface UsePanelLatestData {
data?: PanelData;
error?: DataQueryError;
isLoading: boolean;
hasSeries: boolean;
}
/**
* Subscribes and returns latest panel data from PanelQueryRunner
*/
export const usePanelLatestData = (
panel: PanelModel,
options: GetDataOptions,
checkSchema?: boolean
): UsePanelLatestData => {
const querySubscription = useRef<Unsubscribable>();
const [latestData, setLatestData] = useState<PanelData>();
useEffect(() => {
let lastRev = -1;
let lastUpdate = 0;
querySubscription.current = panel
.getQueryRunner()
.getData(options)
.subscribe({
next: (data) => {
if (checkSchema) {
if (lastRev === data.structureRev) {
const now = Date.now();
const elapsed = now - lastUpdate;
if (elapsed < 10000) {
return; // avoid updates if the schema has not changed for 10s
}
lastUpdate = now;
}
lastRev = data.structureRev ?? -1;
}
setLatestData(data);
},
});
return () => {
if (querySubscription.current) {
querySubscription.current.unsubscribe();
}
};
/**
* Adding separate options to dependencies array to avoid additional hook for comparing previous options with current.
* Otherwise, passing different references to the same object might cause troubles.
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [panel, options.withFieldConfig, options.withTransforms]);
return {
data: latestData,
error: latestData && latestData.error,
isLoading: latestData ? latestData.state === LoadingState.Loading : true,
hasSeries: latestData ? !!latestData.series : false,
};
};