Skip to content

Commit

Permalink
Area + Bar send their tooltip data to redux store (#4521)
Browse files Browse the repository at this point in the history
  • Loading branch information
PavelVanecek committed May 12, 2024
1 parent 2d8c0f0 commit 139a587
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 10 deletions.
48 changes: 45 additions & 3 deletions src/cartesian/Area.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @fileOverview Area
*/
import React, { PureComponent, SVGProps } from 'react';
import React, { PureComponent, SVGProps, useEffect } from 'react';
import clsx from 'clsx';
import Animate from 'react-smooth';
import isFunction from 'lodash/isFunction';
Expand All @@ -15,7 +15,7 @@ import { Layer } from '../container/Layer';
import { LabelList } from '../component/LabelList';
import { Global } from '../util/Global';
import { isNumber, uniqueId, interpolateNumber } from '../util/DataUtils';
import { getCateCoordinateOfLine, getValueByDataKey } from '../util/ChartUtils';
import { getCateCoordinateOfLine, getTooltipNameProp, getValueByDataKey } from '../util/ChartUtils';
import { Props as XAxisProps } from './XAxis';
import { Props as YAxisProps } from './YAxis';
import {
Expand All @@ -35,6 +35,12 @@ import { filterProps, isDotProps } from '../util/ReactUtils';
import type { Payload as LegendPayload } from '../component/DefaultLegendContent';
import { useLegendPayloadDispatch } from '../context/legendPayloadContext';
import { ActivePoints } from '../component/ActivePoints';
import {
addTooltipEntrySettings,
removeTooltipEntrySettings,
TooltipPayloadConfiguration,
} from '../state/tooltipSlice';
import { useAppDispatch } from '../state/hooks';

interface AreaPointItem extends CurvePoint {
value?: number | number[];
Expand Down Expand Up @@ -130,6 +136,36 @@ function SetAreaLegend(props: Props): null {
return null;
}

function getTooltipEntrySettings(props: Props): TooltipPayloadConfiguration {
const { dataKey, data, stroke, strokeWidth, fill, name, hide, unit } = props;
return {
dataDefinedOnItem: data,
settings: {
stroke,
strokeWidth,
fill,
dataKey,
name: getTooltipNameProp(name, dataKey),
hide,
type: props.tooltipType,
color: getLegendItemColor(stroke, fill),
unit,
},
};
}

function SetTooltipEntrySettings(props: Props): null {
const dispatch = useAppDispatch();
useEffect(() => {
const tooltipEntrySettings: TooltipPayloadConfiguration = getTooltipEntrySettings(props);
dispatch(addTooltipEntrySettings(tooltipEntrySettings));
return () => {
dispatch(removeTooltipEntrySettings(tooltipEntrySettings));
};
}, [props, dispatch]);
return null;
}

export class Area extends PureComponent<Props, State> {
static displayName = 'Area';

Expand Down Expand Up @@ -581,7 +617,12 @@ export class Area extends PureComponent<Props, State> {
this.props;

if (hide || !points || !points.length) {
return <SetAreaLegend {...this.props} />;
return (
<>
<SetAreaLegend {...this.props} />
<SetTooltipEntrySettings {...this.props} />
</>
);
}

const { isAnimationFinished } = this.state;
Expand All @@ -599,6 +640,7 @@ export class Area extends PureComponent<Props, State> {
<>
<Layer className={layerClass}>
<SetAreaLegend {...this.props} />
<SetTooltipEntrySettings {...this.props} />
{needClipX || needClipY ? (
<defs>
<clipPath id={`clipPath-${clipPathId}`}>
Expand Down
47 changes: 45 additions & 2 deletions src/cartesian/Bar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @fileOverview Render a group of bar
*/
import React, { Key, PureComponent, ReactElement } from 'react';
import React, { Key, PureComponent, ReactElement, useEffect } from 'react';
import clsx from 'clsx';
import Animate from 'react-smooth';
import isEqual from 'lodash/isEqual';
Expand All @@ -19,6 +19,7 @@ import {
getBaseValueOfBar,
getCateCoordinateOfBar,
getTooltipItem,
getTooltipNameProp,
getValueByDataKey,
truncateByDomain,
} from '../util/ChartUtils';
Expand Down Expand Up @@ -48,6 +49,12 @@ import {
useMouseLeaveItemDispatch,
useTooltipContext,
} from '../context/tooltipContext';
import { useAppDispatch } from '../state/hooks';
import {
addTooltipEntrySettings,
removeTooltipEntrySettings,
TooltipPayloadConfiguration,
} from '../state/tooltipSlice';

export interface BarRectangleItem extends RectangleProps {
value?: number | [number, number];
Expand Down Expand Up @@ -137,6 +144,36 @@ function SetBarLegend(props: Props): null {
return null;
}

function getTooltipEntrySettings(props: Props): TooltipPayloadConfiguration {
const { dataKey, data, stroke, strokeWidth, fill, name, hide, unit } = props;
return {
dataDefinedOnItem: data,
settings: {
stroke,
strokeWidth,
fill,
dataKey,
name: getTooltipNameProp(name, dataKey),
hide,
type: props.tooltipType,
color: props.fill,
unit,
},
};
}

function SetTooltipEntrySettings(props: Props): null {
const dispatch = useAppDispatch();
useEffect(() => {
const tooltipEntrySettings: TooltipPayloadConfiguration = getTooltipEntrySettings(props);
dispatch(addTooltipEntrySettings(tooltipEntrySettings));
return () => {
dispatch(removeTooltipEntrySettings(tooltipEntrySettings));
};
}, [props, dispatch]);
return null;
}

type BarBackgroundProps = {
background?: ActiveShape<BarProps, SVGPathElement>;
data: BarRectangleItem[];
Expand Down Expand Up @@ -613,7 +650,12 @@ export class Bar extends PureComponent<Props, State> {
id,
} = this.props;
if (hide || !data || !data.length) {
return <SetBarLegend {...this.props} />;
return (
<>
<SetBarLegend {...this.props} />
<SetTooltipEntrySettings {...this.props} />
</>
);
}

const { isAnimationFinished } = this.state;
Expand All @@ -626,6 +668,7 @@ export class Bar extends PureComponent<Props, State> {
return (
<Layer className={layerClass}>
<SetBarLegend {...this.props} />
<SetTooltipEntrySettings {...this.props} />
{needClipX || needClipY ? (
<defs>
<clipPath id={`clipPath-${clipPathId}`}>
Expand Down
3 changes: 2 additions & 1 deletion src/cartesian/Line.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function SetLineLegend(props: Props): null {
}

function getTooltipEntrySettings(props: Props): TooltipPayloadConfiguration {
const { dataKey, data, stroke, strokeWidth, fill, name, hide } = props;
const { dataKey, data, stroke, strokeWidth, fill, name, hide, unit } = props;
return {
dataDefinedOnItem: data,
settings: {
Expand All @@ -135,6 +135,7 @@ function getTooltipEntrySettings(props: Props): TooltipPayloadConfiguration {
hide,
type: props.tooltipType,
color: props.stroke,
unit,
},
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/component/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function TooltipInternal<TValue extends ValueType, TName extends NameType>(props
const viewBox = useViewBox();
const accessibilityLayer = useAccessibilityLayer();
const { active: activeFromContext, payload: payloadFromProps, coordinate, label } = useTooltipContext();
// TODO this will fail tests until Area, Bar, and Line all push their own payloads
// TODO this will fail tests until Tooltip props and tooltipAxis are in Redux
// const payloadFromContext = useAppSelector(selectTooltipPayload);
// const payload = payloadFromContext?.length > 0 ? payloadFromContext : payloadFromProps;
const payload = payloadFromProps;
Expand Down
2 changes: 1 addition & 1 deletion src/state/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function selectTooltipPayload(state: RechartsRootState): TooltipPayload |

const sliced = getSliced(finalData, dataStartIndex, dataEndIndex);

// TODO settings coming from Tooltip props
// TODO settings coming from Tooltip props, and tooltipAxis
const tooltipPayload = sliced?.[activeIndex];
const tooltipEntry = getTooltipEntry({
tooltipEntrySettings: settings,
Expand Down
7 changes: 5 additions & 2 deletions src/util/ChartUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1357,9 +1357,12 @@ export function getTooltipEntry({
};
}

export function getTooltipNameProp(nameFromItem: string | undefined, dataKey: DataKey<any>): string | undefined {
export function getTooltipNameProp(
nameFromItem: string | number | undefined,
dataKey: DataKey<any>,
): string | undefined {
if (nameFromItem) {
return nameFromItem;
return String(nameFromItem);
}
if (typeof dataKey === 'string') {
return dataKey;
Expand Down
4 changes: 4 additions & 0 deletions test/state/selectors.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ describe('selectTooltipPayload', () => {
fill: 'green',
dataKey: 'x',
name: 'foo',
unit: 'bar',
},
dataDefinedOnItem: [
{ x: 8, y: 9 },
Expand All @@ -138,6 +139,7 @@ describe('selectTooltipPayload', () => {
fill: 'green',
payload: { x: 10, y: 11 },
value: 10,
unit: 'bar',
};
store.dispatch(addTooltipEntrySettings(tooltipSettings1));
store.dispatch(addTooltipEntrySettings(tooltipSettings2));
Expand All @@ -154,6 +156,7 @@ describe('selectTooltipPayload', () => {
fill: 'green',
dataKey: 'y',
name: 'foo',
unit: 'bar',
},
dataDefinedOnItem: undefined,
};
Expand All @@ -173,6 +176,7 @@ describe('selectTooltipPayload', () => {
fill: 'green',
payload: { x: 1, y: 2 },
value: 2,
unit: 'bar',
};

expect(selectTooltipPayload(store.getState())).toEqual([expectedEntry]);
Expand Down

0 comments on commit 139a587

Please sign in to comment.