StructureRev: use deep equals for structure revision change detection (#53920)

This commit is contained in:
Ryan McKinley 2022-08-19 08:29:23 -07:00 committed by GitHub
parent 88419aa8fe
commit 7cbf6015db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 16 deletions

View File

@ -183,7 +183,7 @@ describe('test comparisons', () => {
expect(compareDataFrameStructures(a, b)).toBeFalsy(); expect(compareDataFrameStructures(a, b)).toBeFalsy();
}); });
it('does not compare deeply', () => { it('does deep comparison', () => {
const a = { const a = {
...frameB, ...frameB,
fields: [ fields: [
@ -218,7 +218,7 @@ describe('test comparisons', () => {
], ],
}; };
expect(compareDataFrameStructures(a, b)).toBeFalsy(); expect(compareDataFrameStructures(a, b)).toBeTruthy();
}); });
}); });
}); });

View File

@ -1,3 +1,5 @@
import { isEqual } from 'lodash';
import { DataFrame } from '../types/dataFrame'; import { DataFrame } from '../types/dataFrame';
/** /**
@ -8,10 +10,6 @@ import { DataFrame } from '../types/dataFrame';
* ``` * ```
* compareArrayValues(a, b, framesHaveSameStructure); * compareArrayValues(a, b, framesHaveSameStructure);
* ``` * ```
* NOTE: this does a shallow check on the FieldConfig properties, when using the query
* editor, this should be sufficient, however if applications are mutating properties
* deep in the FieldConfig this will not recognize a change
*
* @beta * @beta
*/ */
export function compareDataFrameStructures(a: DataFrame, b: DataFrame, skipConfig?: boolean): boolean { export function compareDataFrameStructures(a: DataFrame, b: DataFrame, skipConfig?: boolean): boolean {
@ -63,11 +61,9 @@ export function compareDataFrameStructures(a: DataFrame, b: DataFrame, skipConfi
if (key === 'interval') { if (key === 'interval') {
continue; continue;
} }
if (key === 'custom') {
if (!shallowCompare(cfgA[key], cfgB[key])) { // Deep comparison on all object properties
return false; if (!isEqual(cfgA[key], cfgB[key])) {
}
} else if (cfgA[key] !== cfgB[key]) {
return false; return false;
} }
} }

View File

@ -1,6 +1,15 @@
import React, { useState, useMemo, useEffect, useRef } from 'react'; import React, { useState, useMemo, useEffect, useRef } from 'react';
import { usePrevious } from 'react-use';
import { applyFieldOverrides, FieldConfigSource, getTimeZone, PanelData, PanelPlugin } from '@grafana/data'; import {
applyFieldOverrides,
FieldConfigSource,
getTimeZone,
PanelData,
PanelPlugin,
compareArrayValues,
compareDataFrameStructures,
} from '@grafana/data';
import { PanelRendererProps } from '@grafana/runtime'; import { PanelRendererProps } from '@grafana/runtime';
import { ErrorBoundaryAlert, useTheme2 } from '@grafana/ui'; import { ErrorBoundaryAlert, useTheme2 } from '@grafana/ui';
import { appEvents } from 'app/core/core'; import { appEvents } from 'app/core/core';
@ -112,18 +121,29 @@ function useFieldOverrides(
timeZone: string timeZone: string
): PanelData | undefined { ): PanelData | undefined {
const fieldConfig = defaultOptions?.fieldConfig; const fieldConfig = defaultOptions?.fieldConfig;
const series = data?.series;
const fieldConfigRegistry = plugin?.fieldConfigRegistry; const fieldConfigRegistry = plugin?.fieldConfigRegistry;
const theme = useTheme2(); const theme = useTheme2();
const structureRev = useRef(0); const structureRev = useRef(0);
const prevSeries = usePrevious(data?.series);
return useMemo(() => { return useMemo(() => {
if (!fieldConfigRegistry || !fieldConfig || !data) { if (!fieldConfigRegistry || !fieldConfig || !data) {
return; return;
} }
structureRev.current = structureRev.current + 1;
const series = data?.series;
if (
data.structureRev == null &&
series &&
prevSeries &&
!compareArrayValues(series, prevSeries, compareDataFrameStructures)
) {
structureRev.current++;
}
return { return {
structureRev: structureRev.current,
...data, ...data,
series: applyFieldOverrides({ series: applyFieldOverrides({
data: series, data: series,
@ -133,7 +153,6 @@ function useFieldOverrides(
theme, theme,
timeZone, timeZone,
}), }),
structureRev: structureRev.current,
}; };
}, [fieldConfigRegistry, fieldConfig, data, series, timeZone, theme]); }, [fieldConfigRegistry, fieldConfig, data, prevSeries, timeZone, theme]);
} }