Skip to content

Commit

Permalink
fix: Improve charts performance when fit-height is used (#1366)
Browse files Browse the repository at this point in the history
  • Loading branch information
pan-kot authored Jul 26, 2023
1 parent f94e679 commit 8d643d6
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 22 deletions.
12 changes: 4 additions & 8 deletions src/area-chart/model/use-chart-model.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { AreaChartProps } from '../interfaces';
import React, { useEffect, useMemo, useRef, RefObject, MouseEvent, useState } from 'react';
import React, { useEffect, useMemo, useRef, RefObject, MouseEvent } from 'react';
import { findClosest, circleIndex } from './utils';

import { nodeContains } from '../../internal/utils/dom';
Expand All @@ -15,7 +15,7 @@ import { ChartModel } from './index';
import { ChartPlotRef } from '../../internal/components/chart-plot';
import { throttle } from '../../internal/utils/throttle';
import { useReaction } from '../async-store';
import { useResizeObserver } from '../../internal/hooks/container-queries';
import { useHeightMeasure } from '../../internal/hooks/container-queries/use-height-measure';

const MAX_HOVER_MARGIN = 6;
const SVG_HOVER_THROTTLE = 25;
Expand Down Expand Up @@ -59,12 +59,8 @@ export default function useChartModel<T extends AreaChartProps.DataTypes>({
const verticalMarkerRef = useRef<SVGLineElement>(null);

const plotMeasureRef = useRef<SVGLineElement>(null);
const [measuredHeight, setHeight] = useState(0);
useResizeObserver(
() => plotMeasureRef.current,
entry => fitHeight && setHeight(entry.borderBoxHeight)
);
const height = fitHeight ? measuredHeight : explicitHeight;
const hasVisibleSeries = series.length > 0;
const height = useHeightMeasure(() => plotMeasureRef.current, !fitHeight, [hasVisibleSeries]) ?? explicitHeight;

const stableSetVisibleSeries = useStableEventHandler(setVisibleSeries);

Expand Down
20 changes: 20 additions & 0 deletions src/internal/hooks/container-queries/use-height-measure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

import { useCallback, useState } from 'react';
import { useResizeObserver } from './use-resize-observer';

/**
* Conditional resize observer for border box height used in charts.
*/
export function useHeightMeasure(
getMeasure: () => null | HTMLElement | SVGElement,
skip = false,
deps: React.DependencyList = []
) {
const [measuredHeight, setHeight] = useState(0);
// eslint-disable-next-line react-hooks/exhaustive-deps
const stableGetMeasure = useCallback(getMeasure, deps);
useResizeObserver(stableGetMeasure, entry => !skip && setHeight(entry.borderBoxHeight));
return !skip ? measuredHeight : undefined;
}
10 changes: 3 additions & 7 deletions src/mixed-line-bar-chart/chart-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import useContainerWidth from '../internal/utils/use-container-width';
import { useMergeRefs } from '../internal/hooks/use-merge-refs';
import { nodeBelongs } from '../internal/utils/node-belongs';
import { CartesianChartContainer } from '../internal/components/cartesian-chart/chart-container';
import { useResizeObserver } from '../internal/hooks/container-queries';
import { useHeightMeasure } from '../internal/hooks/container-queries/use-height-measure';

const LEFT_LABELS_MARGIN = 16;
const BOTTOM_LABELS_OFFSET = 12;
Expand Down Expand Up @@ -122,12 +122,8 @@ export default function ChartContainer<T extends ChartDataTypes>({
const popoverRef = useRef<HTMLElement | null>(null);

const plotMeasureRef = useRef<SVGLineElement>(null);
const [measuredHeight, setHeight] = useState(0);
useResizeObserver(
() => plotMeasureRef.current,
entry => fitHeight && setHeight(entry.borderBoxHeight)
);
const plotHeight = fitHeight ? measuredHeight : explicitPlotHeight;
const measuredHeight = useHeightMeasure(() => plotMeasureRef.current, !fitHeight || !bottomLabelsHeight);
const plotHeight = fitHeight ? (bottomLabelsHeight ? measuredHeight ?? 0 : 0) : explicitPlotHeight;

const isRefresh = useVisualRefresh();

Expand Down
9 changes: 2 additions & 7 deletions src/pie-chart/pie-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import { SomeRequired } from '../internal/types';
import { useInternalI18n } from '../internal/i18n/context';
import { nodeBelongs } from '../internal/utils/node-belongs';
import clsx from 'clsx';
import { useResizeObserver } from '../internal/hooks/container-queries';
import { useVisualRefresh } from '../internal/hooks/use-visual-mode';
import { useHeightMeasure } from '../internal/hooks/container-queries/use-height-measure';

export interface InternalChartDatum<T> {
index: number;
Expand Down Expand Up @@ -90,12 +90,7 @@ export default <T extends PieChartProps.Datum>({
const hasLabels = !(hideTitles && hideDescriptions);
const isRefresh = useVisualRefresh();

const [measuredHeight, setHeight] = useState(0);
useResizeObserver(
() => plotRef.current?.svg ?? null,
entry => fitHeight && setHeight(entry.borderBoxHeight)
);
const height = fitHeight ? measuredHeight : explicitHeight;
const height = useHeightMeasure(() => plotRef.current?.svg ?? null, !fitHeight) ?? explicitHeight;

const dimensions = useMemo(
() =>
Expand Down

0 comments on commit 8d643d6

Please sign in to comment.