mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PlotLegend: Memoize for better performance (#56123)
This commit is contained in:
parent
08ffcfdf16
commit
e819ed0f51
@ -9,8 +9,8 @@ export interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
gradient?: string;
|
||||
}
|
||||
|
||||
export const SeriesIcon = React.forwardRef<HTMLDivElement, Props>(
|
||||
({ color, className, gradient, ...restProps }, ref) => {
|
||||
export const SeriesIcon = React.memo(
|
||||
React.forwardRef<HTMLDivElement, Props>(({ color, className, gradient, ...restProps }, ref) => {
|
||||
const theme = useTheme2();
|
||||
let cssColor: string;
|
||||
|
||||
@ -36,7 +36,7 @@ export const SeriesIcon = React.forwardRef<HTMLDivElement, Props>(
|
||||
};
|
||||
|
||||
return <div data-testid="series-icon" ref={ref} className={className} style={styles} {...restProps} />;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
SeriesIcon.displayName = 'SeriesIcon';
|
||||
|
@ -110,4 +110,4 @@ export function VizLegend<T>({
|
||||
}
|
||||
}
|
||||
|
||||
VizLegend.displayName = 'Legend';
|
||||
VizLegend.displayName = 'VizLegend';
|
||||
|
@ -15,7 +15,7 @@ interface Props {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName, color, gradient, readonly }) => {
|
||||
export const VizLegendSeriesIcon = React.memo(({ seriesName, color, gradient, readonly }: Props) => {
|
||||
const { onSeriesColorChange } = usePanelContext();
|
||||
const onChange = useCallback(
|
||||
(color: string) => {
|
||||
@ -40,6 +40,6 @@ export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName
|
||||
);
|
||||
}
|
||||
return <SeriesIcon color={color} gradient={gradient} />;
|
||||
};
|
||||
});
|
||||
|
||||
VizLegendSeriesIcon.displayName = 'VizLegendSeriesIcon';
|
||||
|
@ -27,115 +27,110 @@ interface PlotLegendProps extends VizLegendOptions, Omit<VizLayoutLegendProps, '
|
||||
config: UPlotConfigBuilder;
|
||||
}
|
||||
|
||||
export const PlotLegend: React.FC<PlotLegendProps> = ({
|
||||
data,
|
||||
config,
|
||||
placement,
|
||||
calcs,
|
||||
displayMode,
|
||||
...vizLayoutLegendProps
|
||||
}) => {
|
||||
const theme = useTheme2();
|
||||
const legendItems = config
|
||||
.getSeries()
|
||||
.map<VizLegendItem | undefined>((s) => {
|
||||
const seriesConfig = s.props;
|
||||
const fieldIndex = seriesConfig.dataFrameFieldIndex;
|
||||
const axisPlacement = config.getAxisPlacement(s.props.scaleKey);
|
||||
export const PlotLegend: React.FC<PlotLegendProps> = React.memo(
|
||||
({ data, config, placement, calcs, displayMode, ...vizLayoutLegendProps }) => {
|
||||
const theme = useTheme2();
|
||||
const legendItems = config
|
||||
.getSeries()
|
||||
.map<VizLegendItem | undefined>((s) => {
|
||||
const seriesConfig = s.props;
|
||||
const fieldIndex = seriesConfig.dataFrameFieldIndex;
|
||||
const axisPlacement = config.getAxisPlacement(s.props.scaleKey);
|
||||
|
||||
if (!fieldIndex) {
|
||||
return undefined;
|
||||
}
|
||||
if (!fieldIndex) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const field = data[fieldIndex.frameIndex]?.fields[fieldIndex.fieldIndex];
|
||||
const field = data[fieldIndex.frameIndex]?.fields[fieldIndex.fieldIndex];
|
||||
|
||||
if (!field || field.config.custom?.hideFrom?.legend) {
|
||||
return undefined;
|
||||
}
|
||||
if (!field || field.config.custom?.hideFrom?.legend) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const label = getFieldDisplayName(field, data[fieldIndex.frameIndex]!, data);
|
||||
const scaleColor = getFieldSeriesColor(field, theme);
|
||||
const seriesColor = scaleColor.color;
|
||||
const label = getFieldDisplayName(field, data[fieldIndex.frameIndex]!, data);
|
||||
const scaleColor = getFieldSeriesColor(field, theme);
|
||||
const seriesColor = scaleColor.color;
|
||||
|
||||
return {
|
||||
disabled: !(seriesConfig.show ?? true),
|
||||
fieldIndex,
|
||||
color: seriesColor,
|
||||
label,
|
||||
yAxis: axisPlacement === AxisPlacement.Left ? 1 : 2,
|
||||
getDisplayValues: () => {
|
||||
if (!calcs?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const fmt = field.display ?? defaultFormatter;
|
||||
let countFormatter: DisplayProcessor | null = null;
|
||||
|
||||
const fieldCalcs = reduceField({
|
||||
field,
|
||||
reducers: calcs,
|
||||
});
|
||||
|
||||
return calcs.map<DisplayValue>((reducerId) => {
|
||||
const fieldReducer = fieldReducers.get(reducerId);
|
||||
let formatter = fmt;
|
||||
|
||||
if (fieldReducer.id === ReducerID.diffperc) {
|
||||
formatter = getDisplayProcessor({
|
||||
field: {
|
||||
...field,
|
||||
config: {
|
||||
...field.config,
|
||||
unit: 'percent',
|
||||
},
|
||||
},
|
||||
theme,
|
||||
});
|
||||
return {
|
||||
disabled: !(seriesConfig.show ?? true),
|
||||
fieldIndex,
|
||||
color: seriesColor,
|
||||
label,
|
||||
yAxis: axisPlacement === AxisPlacement.Left ? 1 : 2,
|
||||
getDisplayValues: () => {
|
||||
if (!calcs?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (
|
||||
fieldReducer.id === ReducerID.count ||
|
||||
fieldReducer.id === ReducerID.changeCount ||
|
||||
fieldReducer.id === ReducerID.distinctCount
|
||||
) {
|
||||
if (!countFormatter) {
|
||||
countFormatter = getDisplayProcessor({
|
||||
const fmt = field.display ?? defaultFormatter;
|
||||
let countFormatter: DisplayProcessor | null = null;
|
||||
|
||||
const fieldCalcs = reduceField({
|
||||
field,
|
||||
reducers: calcs,
|
||||
});
|
||||
|
||||
return calcs.map<DisplayValue>((reducerId) => {
|
||||
const fieldReducer = fieldReducers.get(reducerId);
|
||||
let formatter = fmt;
|
||||
|
||||
if (fieldReducer.id === ReducerID.diffperc) {
|
||||
formatter = getDisplayProcessor({
|
||||
field: {
|
||||
...field,
|
||||
config: {
|
||||
...field.config,
|
||||
unit: 'none',
|
||||
unit: 'percent',
|
||||
},
|
||||
},
|
||||
theme,
|
||||
});
|
||||
}
|
||||
formatter = countFormatter;
|
||||
}
|
||||
|
||||
return {
|
||||
...formatter(fieldCalcs[reducerId]),
|
||||
title: fieldReducer.name,
|
||||
description: fieldReducer.description,
|
||||
};
|
||||
});
|
||||
},
|
||||
getItemKey: () => `${label}-${fieldIndex.frameIndex}-${fieldIndex.fieldIndex}`,
|
||||
};
|
||||
})
|
||||
.filter((i) => i !== undefined) as VizLegendItem[];
|
||||
if (
|
||||
fieldReducer.id === ReducerID.count ||
|
||||
fieldReducer.id === ReducerID.changeCount ||
|
||||
fieldReducer.id === ReducerID.distinctCount
|
||||
) {
|
||||
if (!countFormatter) {
|
||||
countFormatter = getDisplayProcessor({
|
||||
field: {
|
||||
...field,
|
||||
config: {
|
||||
...field.config,
|
||||
unit: 'none',
|
||||
},
|
||||
},
|
||||
theme,
|
||||
});
|
||||
}
|
||||
formatter = countFormatter;
|
||||
}
|
||||
|
||||
return (
|
||||
<VizLayout.Legend placement={placement} {...vizLayoutLegendProps}>
|
||||
<VizLegend
|
||||
placement={placement}
|
||||
items={legendItems}
|
||||
displayMode={displayMode}
|
||||
sortBy={vizLayoutLegendProps.sortBy}
|
||||
sortDesc={vizLayoutLegendProps.sortDesc}
|
||||
/>
|
||||
</VizLayout.Legend>
|
||||
);
|
||||
};
|
||||
return {
|
||||
...formatter(fieldCalcs[reducerId]),
|
||||
title: fieldReducer.name,
|
||||
description: fieldReducer.description,
|
||||
};
|
||||
});
|
||||
},
|
||||
getItemKey: () => `${label}-${fieldIndex.frameIndex}-${fieldIndex.fieldIndex}`,
|
||||
};
|
||||
})
|
||||
.filter((i) => i !== undefined) as VizLegendItem[];
|
||||
|
||||
return (
|
||||
<VizLayout.Legend placement={placement} {...vizLayoutLegendProps}>
|
||||
<VizLegend
|
||||
placement={placement}
|
||||
items={legendItems}
|
||||
displayMode={displayMode}
|
||||
sortBy={vizLayoutLegendProps.sortBy}
|
||||
sortDesc={vizLayoutLegendProps.sortDesc}
|
||||
/>
|
||||
</VizLayout.Legend>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
PlotLegend.displayName = 'PlotLegend';
|
||||
|
Loading…
Reference in New Issue
Block a user