From a7b6c017f6664ec295adea2977d83880f7d2ea30 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 4 Jun 2024 12:17:46 +0200 Subject: [PATCH 1/8] Add `Initializable` type and behaviour to allow checking if a context is in scope --- .../HighlightedProvider/HighlightedContext.ts | 8 +++++--- .../HighlightedProvider/HighlightedProvider.tsx | 4 +++- .../HighlightedProvider/useHighlighted.ts | 4 ++-- .../HighlightedProvider/useItemHighlighted.ts | 2 +- .../src/context/SeriesContextProvider.tsx | 11 ++++++++--- packages/x-charts/src/context/context.types.ts | 3 +++ packages/x-charts/src/hooks/useSeries.ts | 16 ++++++++-------- packages/x-charts/src/hooks/useSvgRef.ts | 2 +- 8 files changed, 31 insertions(+), 19 deletions(-) create mode 100644 packages/x-charts/src/context/context.types.ts diff --git a/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts b/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts index eef7143a95f9..1c512038a940 100644 --- a/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts +++ b/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import { SeriesId } from '../../models/seriesType/common'; +import { Initializable } from '../context.types'; /** * The data of the highlighted item. @@ -59,16 +60,17 @@ export type HighlightScope = { fade?: FadeOptions; }; -export type HighlightedState = { +export interface HighlightedState { highlightScope?: Partial; highlightedItem: HighlightItemData | null; setHighlighted: (item: HighlightItemData) => void; clearHighlighted: () => void; isHighlighted: (input: HighlightItemData) => boolean; isFaded: (input: HighlightItemData) => boolean; -}; +} -export const HighlightedContext = React.createContext({ +export const HighlightedContext = React.createContext>({ + isInitialized: false, highlightedItem: null, setHighlighted: () => {}, clearHighlighted: () => {}, diff --git a/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx b/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx index e42bcc3d5cd0..eb7518e892ab 100644 --- a/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx +++ b/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx @@ -12,6 +12,7 @@ import { createIsHighlighted } from './createIsHighlighted'; import { useSeries } from '../../hooks/useSeries'; import { ChartSeriesType } from '../../models/seriesType/config'; import { SeriesId } from '../../models/seriesType/common'; +import { Initializable } from '../context.types'; export type HighlightedProviderProps = { children: React.ReactNode; @@ -67,8 +68,9 @@ function HighlightedProvider({ ? seriesById.get(highlightedItem.seriesId) ?? undefined : undefined; - const providerValue = React.useMemo(() => { + const providerValue = React.useMemo>(() => { return { + isInitialized: true, highlightScope, highlightedItem, setHighlighted: (itemData) => { diff --git a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts index f8db7950e123..7386192c3eaf 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts +++ b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts @@ -9,9 +9,9 @@ import { HighlightedContext, HighlightedState } from './HighlightedContext'; * @returns {HighlightedState} the state of the chart */ export function useHighlighted(): HighlightedState { - const highlighted = React.useContext(HighlightedContext); + const { isInitialized, ...highlighted } = React.useContext(HighlightedContext); - if (highlighted === undefined) { + if (!isInitialized) { throw new Error( [ 'MUI X: Could not find the highlighted ref context.', diff --git a/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts b/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts index d019b9c661bd..fafa16bafd6d 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts +++ b/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts @@ -24,7 +24,7 @@ export type ItemHighlightedState = { export function useItemHighlighted(item: HighlightItemData | null): ItemHighlightedState { const highlighted = React.useContext(HighlightedContext); - if (highlighted === undefined) { + if (!highlighted.isInitialized) { throw new Error( [ 'MUI X: Could not find the highlighted ref context.', diff --git a/packages/x-charts/src/context/SeriesContextProvider.tsx b/packages/x-charts/src/context/SeriesContextProvider.tsx index e39746611bd4..eed7e26e9f9c 100644 --- a/packages/x-charts/src/context/SeriesContextProvider.tsx +++ b/packages/x-charts/src/context/SeriesContextProvider.tsx @@ -13,6 +13,7 @@ import { FormatterResult, } from '../models/seriesType/config'; import { ChartsColorPalette, blueberryTwilightPalette } from '../colorPalettes'; +import { Initializable } from './context.types'; export type SeriesContextProviderProps = { dataset?: DatasetType; @@ -32,7 +33,9 @@ export type SeriesContextProviderProps = { export type FormattedSeries = { [type in ChartSeriesType]?: FormatterResult }; -export const SeriesContext = React.createContext({}); +export const SeriesContext = React.createContext>({ + isInitialized: false, +}); if (process.env.NODE_ENV !== 'production') { SeriesContext.displayName = 'SeriesContext'; @@ -93,12 +96,14 @@ function SeriesContextProvider(props: SeriesContextProviderProps) { const theme = useTheme(); const formattedSeries = React.useMemo( - () => - formatSeries( + () => ({ + isInitialized: true, + ...formatSeries( series, typeof colors === 'function' ? colors(theme.palette.mode) : colors, dataset as DatasetType, ), + }), [series, colors, theme.palette.mode, dataset], ); diff --git a/packages/x-charts/src/context/context.types.ts b/packages/x-charts/src/context/context.types.ts new file mode 100644 index 000000000000..12a19a8720ad --- /dev/null +++ b/packages/x-charts/src/context/context.types.ts @@ -0,0 +1,3 @@ +export type Initializable = { + isInitialized: boolean; +} & T; diff --git a/packages/x-charts/src/hooks/useSeries.ts b/packages/x-charts/src/hooks/useSeries.ts index 12817cb944eb..2c3ed4d314e9 100644 --- a/packages/x-charts/src/hooks/useSeries.ts +++ b/packages/x-charts/src/hooks/useSeries.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import { SeriesContext } from '../context/SeriesContextProvider'; +import { FormattedSeries, SeriesContext } from '../context/SeriesContextProvider'; /** * Get access to the internal state of series. @@ -7,10 +7,10 @@ import { SeriesContext } from '../context/SeriesContextProvider'; * { seriesType?: { series: { id1: precessedValue, ... }, seriesOrder: [id1, ...] } } * @returns FormattedSeries series */ -export function useSeries() { - const series = React.useContext(SeriesContext); +export function useSeries(): FormattedSeries { + const { isInitialized, ...series } = React.useContext(SeriesContext); - if (series === undefined) { + if (!isInitialized) { throw new Error( [ 'MUI X: Could not find the series ref context.', @@ -29,7 +29,7 @@ export function useSeries() { * - seriesOrder: the array of series ids. * @returns { series: Record; seriesOrder: SeriesId[]; } | undefined pieSeries */ -export function usePieSeries() { +export function usePieSeries(): FormattedSeries['pie'] { const series = useSeries(); return React.useMemo(() => series.pie, [series.pie]); @@ -42,7 +42,7 @@ export function usePieSeries() { * - seriesOrder: the array of series ids. * @returns { series: Record; seriesOrder: SeriesId[]; } | undefined lineSeries */ -export function useLineSeries() { +export function useLineSeries(): FormattedSeries['line'] { const series = useSeries(); return React.useMemo(() => series.line, [series.line]); @@ -55,7 +55,7 @@ export function useLineSeries() { * - seriesOrder: the array of series ids. * @returns { series: Record; seriesOrder: SeriesId[]; } | undefined barSeries */ -export function useBarSeries() { +export function useBarSeries(): FormattedSeries['bar'] { const series = useSeries(); return React.useMemo(() => series.bar, [series.bar]); @@ -68,7 +68,7 @@ export function useBarSeries() { * - seriesOrder: the array of series ids. * @returns { series: Record; seriesOrder: SeriesId[]; } | undefined scatterSeries */ -export function useScatterSeries() { +export function useScatterSeries(): FormattedSeries['scatter'] { const series = useSeries(); return React.useMemo(() => series.scatter, [series.scatter]); diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index 268222985047..01371bbd3b92 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -4,7 +4,7 @@ import { SvgContext } from '../context/DrawingProvider'; export function useSvgRef(): React.MutableRefObject { const svgRef = React.useContext(SvgContext); - if (svgRef === undefined) { + if (svgRef.current === undefined) { throw new Error( [ 'MUI X: Could not find the svg ref context.', From c09689bfca7373f0b2f5cb0a79b5c12a96eb8b2b Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 4 Jun 2024 12:28:18 +0200 Subject: [PATCH 2/8] Make use to use the `useSeries` functions instead of `useContext` --- packages/x-charts/src/BarChart/BarPlot.tsx | 4 ++-- packages/x-charts/src/ChartsLegend/ChartsLegend.tsx | 4 ++-- .../ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx | 8 ++++---- .../src/ChartsTooltip/ChartsAxisTooltipContent.tsx | 4 ++-- .../src/ChartsTooltip/ChartsItemTooltipContent.tsx | 6 ++---- .../src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx | 4 ++-- packages/x-charts/src/LineChart/AreaPlot.tsx | 4 ++-- packages/x-charts/src/LineChart/LineHighlightPlot.tsx | 4 ++-- packages/x-charts/src/LineChart/LinePlot.tsx | 4 ++-- packages/x-charts/src/LineChart/MarkPlot.tsx | 4 ++-- packages/x-charts/src/PieChart/PiePlot.tsx | 4 ++-- packages/x-charts/src/ScatterChart/ScatterPlot.tsx | 4 ++-- .../x-charts/src/context/CartesianContextProvider.tsx | 4 ++-- 13 files changed, 28 insertions(+), 30 deletions(-) diff --git a/packages/x-charts/src/BarChart/BarPlot.tsx b/packages/x-charts/src/BarChart/BarPlot.tsx index 476e4319b916..7ff1e8999a57 100644 --- a/packages/x-charts/src/BarChart/BarPlot.tsx +++ b/packages/x-charts/src/BarChart/BarPlot.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { useTransition } from '@react-spring/web'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; import { BarElement, BarElementSlotProps, BarElementSlots } from './BarElement'; import { AxisDefaultized } from '../models/axis'; @@ -14,6 +13,7 @@ import { BarClipPath } from './BarClipPath'; import { BarLabelItemProps, BarLabelSlotProps, BarLabelSlots } from './BarLabel/BarLabelItem'; import { BarLabelPlot } from './BarLabel/BarLabelPlot'; import { checkScaleErrors } from './checkScaleErrors'; +import { useBarSeries } from '../hooks/useSeries'; /** * Solution of the equations @@ -87,7 +87,7 @@ const useAggregatedData = (): { masksData: MaskData[]; } => { const seriesData = - React.useContext(SeriesContext).bar ?? + useBarSeries() ?? ({ series: {}, stackingGroups: [], seriesOrder: [] } as FormatterResult<'bar'>); const axisData = React.useContext(CartesianContext); const chartId = useChartId(); diff --git a/packages/x-charts/src/ChartsLegend/ChartsLegend.tsx b/packages/x-charts/src/ChartsLegend/ChartsLegend.tsx index 6804c7592f0b..9be1635a6b77 100644 --- a/packages/x-charts/src/ChartsLegend/ChartsLegend.tsx +++ b/packages/x-charts/src/ChartsLegend/ChartsLegend.tsx @@ -4,11 +4,11 @@ import { useSlotProps } from '@mui/base/utils'; import { unstable_composeClasses as composeClasses } from '@mui/utils'; import { useThemeProps, useTheme, Theme } from '@mui/material/styles'; import { AnchorPosition, Direction, getSeriesToDisplay } from './utils'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { ChartsLegendClasses, getLegendUtilityClass } from './chartsLegendClasses'; import { DefaultizedProps } from '../models/helpers'; import { DefaultChartsLegend, LegendRendererProps } from './DefaultChartsLegend'; import { useDrawingArea } from '../hooks'; +import { useSeries } from '../hooks/useSeries'; export interface ChartsLegendSlots { /** @@ -83,7 +83,7 @@ function ChartsLegend(inProps: ChartsLegendProps) { const classes = useUtilityClasses({ ...props, theme }); const drawingArea = useDrawingArea(); - const series = React.useContext(SeriesContext); + const series = useSeries(); const seriesToDisplay = getSeriesToDisplay(series); diff --git a/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx b/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx index 3a7735582e52..f134b0b2f599 100644 --- a/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx +++ b/packages/x-charts/src/ChartsOnAxisClickHandler/ChartsOnAxisClickHandler.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { SvgContext } from '../context/DrawingProvider'; import { InteractionContext } from '../context/InteractionProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; -import { SeriesContext } from '../context/SeriesContextProvider'; +import { useSeries } from '../hooks/useSeries'; +import { useSvgRef } from '../hooks'; type AxisData = { dataIndex: number; @@ -24,8 +24,8 @@ export interface ChartsOnAxisClickHandlerProps { function ChartsOnAxisClickHandler(props: ChartsOnAxisClickHandlerProps) { const { onAxisClick } = props; - const svgRef = React.useContext(SvgContext); - const series = React.useContext(SeriesContext); + const svgRef = useSvgRef(); + const series = useSeries(); const { axis } = React.useContext(InteractionContext); const { xAxisIds, xAxis, yAxisIds, yAxis } = React.useContext(CartesianContext); diff --git a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx index c65b9e1e1786..c1d33d29c210 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx @@ -3,7 +3,6 @@ import PropTypes from 'prop-types'; import { SxProps, Theme } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { AxisInteractionData } from '../context/InteractionProvider'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; import { ChartSeriesDefaultized, ChartSeriesType } from '../models/seriesType/config'; import { AxisDefaultized } from '../models/axis'; @@ -12,6 +11,7 @@ import { DefaultChartsAxisTooltipContent } from './DefaultChartsAxisTooltipConte import { isCartesianSeriesType } from './utils'; import colorGetter from '../internals/colorGetter'; import { ZAxisContext } from '../context/ZAxisContextProvider'; +import { useSeries } from '../hooks/useSeries'; type ChartSeriesDefaultizedWithColorGetter = ChartSeriesDefaultized & { getColor: (dataIndex: number) => string; @@ -61,7 +61,7 @@ function ChartsAxisTooltipContent(props: { const { xAxisIds, xAxis, yAxisIds, yAxis } = React.useContext(CartesianContext); const { zAxisIds, zAxis } = React.useContext(ZAxisContext); - const series = React.useContext(SeriesContext); + const series = useSeries(); const USED_AXIS_ID = isXaxis ? xAxisIds[0] : yAxisIds[0]; diff --git a/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx index 2f7183a6fd93..d77f16af9d47 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx @@ -3,13 +3,13 @@ import PropTypes from 'prop-types'; import { SxProps, Theme } from '@mui/material/styles'; import { useSlotProps } from '@mui/base/utils'; import { ItemInteractionData } from '../context/InteractionProvider'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { ChartSeriesDefaultized, ChartSeriesType } from '../models/seriesType/config'; import { ChartsTooltipClasses } from './chartsTooltipClasses'; import { DefaultChartsItemTooltipContent } from './DefaultChartsItemTooltipContent'; import { CartesianContext } from '../context/CartesianContextProvider'; import colorGetter from '../internals/colorGetter'; import { ZAxisContext } from '../context/ZAxisContextProvider'; +import { useSeries } from '../hooks/useSeries'; export type ChartsItemContentProps = { /** @@ -42,9 +42,7 @@ function ChartsItemTooltipContent(props: { }) { const { content, itemData, sx, classes, contentProps } = props; - const series = React.useContext(SeriesContext)[itemData.type]!.series[ - itemData.seriesId - ] as ChartSeriesDefaultized; + const series = useSeries()[itemData.type]!.series[itemData.seriesId] as ChartSeriesDefaultized; const { xAxis, yAxis, xAxisIds, yAxisIds } = React.useContext(CartesianContext); const { zAxis, zAxisIds } = React.useContext(ZAxisContext); diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index c66a23fc06e2..170c4a71e112 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -4,13 +4,13 @@ import { Delaunay } from 'd3-delaunay'; import useEnhancedEffect from '@mui/utils/useEnhancedEffect'; import { InteractionContext } from '../context/InteractionProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { getValueToPositionMapper } from '../hooks/useScale'; import { getSVGPoint } from '../internals/utils'; import { ScatterItemIdentifier } from '../models'; import { SeriesId } from '../models/seriesType/common'; import { useDrawingArea, useSvgRef } from '../hooks'; import { useHighlighted } from '../context'; +import { useScatterSeries } from '../hooks/useSeries'; export type ChartsVoronoiHandlerProps = { /** @@ -35,7 +35,7 @@ function ChartsVoronoiHandler(props: ChartsVoronoiHandlerProps) { const { xAxis, yAxis, xAxisIds, yAxisIds } = React.useContext(CartesianContext); const { dispatch } = React.useContext(InteractionContext); - const { series, seriesOrder } = React.useContext(SeriesContext).scatter ?? {}; + const { series, seriesOrder } = useScatterSeries() ?? {}; const voronoiRef = React.useRef>({}); const delauneyRef = React.useRef | undefined>(undefined); diff --git a/packages/x-charts/src/LineChart/AreaPlot.tsx b/packages/x-charts/src/LineChart/AreaPlot.tsx index 9334bbc122b4..51a62066c83a 100644 --- a/packages/x-charts/src/LineChart/AreaPlot.tsx +++ b/packages/x-charts/src/LineChart/AreaPlot.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { area as d3Area } from 'd3-shape'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; import { AreaElement, @@ -14,6 +13,7 @@ import getCurveFactory from '../internals/getCurve'; import { DEFAULT_X_AXIS_KEY } from '../constants'; import { LineItemIdentifier } from '../models/seriesType/line'; import { useChartGradient } from '../internals/components/ChartsAxesGradients'; +import { useLineSeries } from '../hooks/useSeries'; export interface AreaPlotSlots extends AreaElementSlots {} @@ -34,7 +34,7 @@ export interface AreaPlotProps } const useAggregatedData = () => { - const seriesData = React.useContext(SeriesContext).line; + const seriesData = useLineSeries(); const axisData = React.useContext(CartesianContext); if (seriesData === undefined) { diff --git a/packages/x-charts/src/LineChart/LineHighlightPlot.tsx b/packages/x-charts/src/LineChart/LineHighlightPlot.tsx index b2dd6ec8b08d..25343dd4c129 100644 --- a/packages/x-charts/src/LineChart/LineHighlightPlot.tsx +++ b/packages/x-charts/src/LineChart/LineHighlightPlot.tsx @@ -1,12 +1,12 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; import { LineHighlightElement, LineHighlightElementProps } from './LineHighlightElement'; import { getValueToPositionMapper } from '../hooks/useScale'; import { InteractionContext } from '../context/InteractionProvider'; import { DEFAULT_X_AXIS_KEY } from '../constants'; import getColor from './getColor'; +import { useLineSeries } from '../hooks/useSeries'; export interface LineHighlightPlotSlots { lineHighlight?: React.JSXElementConstructor; @@ -42,7 +42,7 @@ export interface LineHighlightPlotProps extends React.SVGAttributes { - const seriesData = React.useContext(SeriesContext).line; + const seriesData = useLineSeries(); const axisData = React.useContext(CartesianContext); if (seriesData === undefined) { diff --git a/packages/x-charts/src/LineChart/MarkPlot.tsx b/packages/x-charts/src/LineChart/MarkPlot.tsx index 313d1b37db58..23c7695f443e 100644 --- a/packages/x-charts/src/LineChart/MarkPlot.tsx +++ b/packages/x-charts/src/LineChart/MarkPlot.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { CartesianContext } from '../context/CartesianContextProvider'; import { MarkElement, MarkElementProps } from './MarkElement'; import { getValueToPositionMapper } from '../hooks/useScale'; @@ -9,6 +8,7 @@ import { DEFAULT_X_AXIS_KEY } from '../constants'; import { LineItemIdentifier } from '../models/seriesType/line'; import { cleanId } from '../internals/utils'; import getColor from './getColor'; +import { useLineSeries } from '../hooks/useSeries'; export interface MarkPlotSlots { mark?: React.JSXElementConstructor; @@ -55,7 +55,7 @@ export interface MarkPlotProps function MarkPlot(props: MarkPlotProps) { const { slots, slotProps, skipAnimation, onItemClick, ...other } = props; - const seriesData = React.useContext(SeriesContext).line; + const seriesData = useLineSeries(); const axisData = React.useContext(CartesianContext); const chartId = useChartId(); diff --git a/packages/x-charts/src/PieChart/PiePlot.tsx b/packages/x-charts/src/PieChart/PiePlot.tsx index dc85fdea29a2..dcd0e62fe9f4 100644 --- a/packages/x-charts/src/PieChart/PiePlot.tsx +++ b/packages/x-charts/src/PieChart/PiePlot.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import PropTypes from 'prop-types'; -import { SeriesContext } from '../context/SeriesContextProvider'; import { DrawingContext } from '../context/DrawingProvider'; import { PieArcPlot, PieArcPlotProps, PieArcPlotSlotProps, PieArcPlotSlots } from './PieArcPlot'; import { PieArcLabelPlotSlots, PieArcLabelPlotSlotProps, PieArcLabelPlot } from './PieArcLabelPlot'; import { getPercentageValue } from '../internals/utils'; import { getPieCoordinates } from './getPieCoordinates'; +import { usePieSeries } from '../hooks/useSeries'; export interface PiePlotSlots extends PieArcPlotSlots, PieArcLabelPlotSlots {} @@ -36,7 +36,7 @@ export interface PiePlotProps extends Pick; @@ -39,7 +39,7 @@ export interface ScatterPlotProps extends Pick { */ function ScatterPlot(props: ScatterPlotProps) { const { slots, slotProps, onItemClick } = props; - const seriesData = React.useContext(SeriesContext).scatter; + const seriesData = useScatterSeries(); const axisData = React.useContext(CartesianContext); const { zAxis, zAxisIds } = React.useContext(ZAxisContext); diff --git a/packages/x-charts/src/context/CartesianContextProvider.tsx b/packages/x-charts/src/context/CartesianContextProvider.tsx index a6eaeb90f9aa..fb67be299bdb 100644 --- a/packages/x-charts/src/context/CartesianContextProvider.tsx +++ b/packages/x-charts/src/context/CartesianContextProvider.tsx @@ -14,7 +14,6 @@ import { } from '../LineChart/extremums'; import { AxisConfig, AxisDefaultized, isBandScaleConfig, isPointScaleConfig } from '../models/axis'; import { getScale } from '../internals/getScale'; -import { SeriesContext } from './SeriesContextProvider'; import { DEFAULT_X_AXIS_KEY, DEFAULT_Y_AXIS_KEY } from '../constants'; import { CartesianChartSeriesType, @@ -28,6 +27,7 @@ import { getTickNumber } from '../hooks/useTicks'; import { useDrawingArea } from '../hooks/useDrawingArea'; import { SeriesId } from '../models/seriesType/common'; import { getColorScale, getOrdinalColorScale } from '../internals/colorScale'; +import { useSeries } from '../hooks/useSeries'; export type CartesianContextProviderProps = { /** @@ -99,7 +99,7 @@ if (process.env.NODE_ENV !== 'production') { function CartesianContextProvider(props: CartesianContextProviderProps) { const { xAxis: inXAxis, yAxis: inYAxis, dataset, children } = props; - const formattedSeries = React.useContext(SeriesContext); + const formattedSeries = useSeries(); const drawingArea = useDrawingArea(); const xAxis = React.useMemo( From 3018630ecfbb3dce29d6923b21305826f902ab2a Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 4 Jun 2024 12:56:04 +0200 Subject: [PATCH 3/8] Fix logic and add tests --- .../useHighlighted.test.tsx | 41 ++++++++++++++++++ .../HighlightedProvider/useItemHighlighted.ts | 15 ++----- .../x-charts/src/hooks/useSeries.test.tsx | 38 +++++++++++++++++ .../x-charts/src/hooks/useSvgRef.test.tsx | 42 +++++++++++++++++++ packages/x-charts/src/hooks/useSvgRef.ts | 2 +- 5 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx create mode 100644 packages/x-charts/src/hooks/useSeries.test.tsx create mode 100644 packages/x-charts/src/hooks/useSvgRef.test.tsx diff --git a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx new file mode 100644 index 000000000000..b1a17352afa2 --- /dev/null +++ b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import { expect } from 'chai'; +import { ErrorBoundary, createRenderer } from '@mui/internal-test-utils'; +import { useHighlighted } from './useHighlighted'; +import { HighlightedProvider } from './HighlightedProvider'; +import { SeriesContextProvider } from '../SeriesContextProvider'; + +function UseHighlighted() { + const { highlightedItem } = useHighlighted(); + return
{highlightedItem?.seriesId}
; +} + +describe('useHighlighted', () => { + const { render } = createRenderer(); + + it('should throw an error when parent context not present', () => { + expect(() => + render( + + + , + ), + ).toErrorDev([ + 'MUI X: Could not find the highlighted ref context.', + 'It looks like you rendered your component outside of a ChartsContainer parent component.', + 'The above error occurred in the component:', + ]); + }); + + it('should not throw an error when parent context is present', () => { + const { getByText } = render( + + + + + , + ); + + expect(getByText('test-id')).toBeVisible(); + }); +}); diff --git a/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts b/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts index fafa16bafd6d..c6465231cf19 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts +++ b/packages/x-charts/src/context/HighlightedProvider/useItemHighlighted.ts @@ -1,5 +1,5 @@ -import * as React from 'react'; -import { HighlightedContext, HighlightItemData } from './HighlightedContext'; +import { HighlightItemData } from './HighlightedContext'; +import { useHighlighted } from './useHighlighted'; export type ItemHighlightedState = { /** @@ -22,16 +22,7 @@ export type ItemHighlightedState = { * @returns {ItemHighlightedState} the state of the item */ export function useItemHighlighted(item: HighlightItemData | null): ItemHighlightedState { - const highlighted = React.useContext(HighlightedContext); - - if (!highlighted.isInitialized) { - throw new Error( - [ - 'MUI X: Could not find the highlighted ref context.', - 'It looks like you rendered your component outside of a ChartsContainer parent component.', - ].join('\n'), - ); - } + const highlighted = useHighlighted(); if (!item) { return { diff --git a/packages/x-charts/src/hooks/useSeries.test.tsx b/packages/x-charts/src/hooks/useSeries.test.tsx new file mode 100644 index 000000000000..41184514326d --- /dev/null +++ b/packages/x-charts/src/hooks/useSeries.test.tsx @@ -0,0 +1,38 @@ +import * as React from 'react'; +import { expect } from 'chai'; +import { ErrorBoundary, createRenderer } from '@mui/internal-test-utils'; +import { useSeries } from './useSeries'; +import { SeriesContextProvider } from '../context/SeriesContextProvider'; + +function UseSeries() { + const { bar } = useSeries(); + return
{bar?.series['test-id']?.id}
; +} + +describe('useSeries', () => { + const { render } = createRenderer(); + + it('should throw an error when parent context not present', () => { + expect(() => + render( + + + , + ), + ).toErrorDev([ + 'MUI X: Could not find the series ref context.', + 'It looks like you rendered your component outside of a ChartsContainer parent component.', + 'The above error occurred in the component:', + ]); + }); + + it('should not throw an error when parent context is present', () => { + const { getByText } = render( + + + , + ); + + expect(getByText('test-id')).toBeVisible(); + }); +}); diff --git a/packages/x-charts/src/hooks/useSvgRef.test.tsx b/packages/x-charts/src/hooks/useSvgRef.test.tsx new file mode 100644 index 000000000000..2e5d65258500 --- /dev/null +++ b/packages/x-charts/src/hooks/useSvgRef.test.tsx @@ -0,0 +1,42 @@ +import * as React from 'react'; +import { expect } from 'chai'; +import { ErrorBoundary, createRenderer } from '@mui/internal-test-utils'; +import { useSvgRef } from './useSvgRef'; +import { DrawingProvider } from '../context/DrawingProvider'; + +function UseSvgRef() { + const ref = useSvgRef(); + return
{ref.current?.id}
; +} + +describe('useSvgRef', () => { + const { render } = createRenderer(); + + it('should throw an error when parent context not present', () => { + expect(() => + render( + + + , + ), + ).toErrorDev([ + 'MUI X: Could not find the svg ref context.', + 'It looks like you rendered your component outside of a ChartsContainer parent component.', + 'The above error occurred in the component:', + ]); + }); + + it('should not throw an error when parent context is present', () => { + const ref = React.createRef(); + // @ts-expect-error, we don't need to create an actual SVG element + ref.current = { id: 'test-id' } as SVGSVGElement; + + const { getByText } = render( + + + , + ); + + expect(getByText('test-id')).toBeVisible(); + }); +}); diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index 01371bbd3b92..ff1d491adee3 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -4,7 +4,7 @@ import { SvgContext } from '../context/DrawingProvider'; export function useSvgRef(): React.MutableRefObject { const svgRef = React.useContext(SvgContext); - if (svgRef.current === undefined) { + if (svgRef.current === null) { throw new Error( [ 'MUI X: Could not find the svg ref context.', From 704148cf675163c2f85eafb9e4573713cc50c2c9 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Tue, 4 Jun 2024 14:52:29 +0200 Subject: [PATCH 4/8] Fix useSvgRef --- packages/x-charts/src/ChartsTooltip/utils.tsx | 4 +-- .../x-charts/src/context/DrawingProvider.tsx | 14 +++++++-- .../x-charts/src/hooks/useSvgRef.test.tsx | 31 ++++++++++++------- packages/x-charts/src/hooks/useSvgRef.ts | 6 ++-- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/packages/x-charts/src/ChartsTooltip/utils.tsx b/packages/x-charts/src/ChartsTooltip/utils.tsx index 8d465635c61f..89d86636aefc 100644 --- a/packages/x-charts/src/ChartsTooltip/utils.tsx +++ b/packages/x-charts/src/ChartsTooltip/utils.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import { AxisInteractionData, ItemInteractionData } from '../context/InteractionProvider'; -import { SvgContext } from '../context/DrawingProvider'; import { CartesianChartSeriesType, ChartSeriesDefaultized, ChartSeriesType, } from '../models/seriesType/config'; +import { useSvgRef } from '../hooks'; export function generateVirtualElement(mousePosition: { x: number; y: number } | null) { if (mousePosition === null) { @@ -41,7 +41,7 @@ export function generateVirtualElement(mousePosition: { x: number; y: number } | } export function useMouseTracker() { - const svgRef = React.useContext(SvgContext); + const svgRef = useSvgRef(); // Use a ref to avoid rerendering on every mousemove event. const [mousePosition, setMousePosition] = React.useState(null); diff --git a/packages/x-charts/src/context/DrawingProvider.tsx b/packages/x-charts/src/context/DrawingProvider.tsx index 6f418dd8f57e..783354240942 100644 --- a/packages/x-charts/src/context/DrawingProvider.tsx +++ b/packages/x-charts/src/context/DrawingProvider.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import useId from '@mui/utils/useId'; import useChartDimensions from '../hooks/useChartDimensions'; import { LayoutConfig } from '../models/layout'; +import { Initializable } from './context.types'; export interface DrawingProviderProps extends LayoutConfig { children: React.ReactNode; @@ -59,7 +60,14 @@ if (process.env.NODE_ENV !== 'production') { DrawingContext.displayName = 'DrawingContext'; } -export const SvgContext = React.createContext>({ current: null }); +export type SvgContextState = { + svg: React.RefObject; +}; + +export const SvgContext = React.createContext>({ + isInitialized: false, + svg: { current: null }, +}); if (process.env.NODE_ENV !== 'production') { SvgContext.displayName = 'SvgContext'; @@ -75,8 +83,10 @@ export function DrawingProvider(props: DrawingProviderProps) { [chartId, drawingArea], ); + const refValue = React.useMemo(() => ({ isInitialized: true, svg: svgRef }), [svgRef]); + return ( - + {children} ); diff --git a/packages/x-charts/src/hooks/useSvgRef.test.tsx b/packages/x-charts/src/hooks/useSvgRef.test.tsx index 2e5d65258500..5f74f1217442 100644 --- a/packages/x-charts/src/hooks/useSvgRef.test.tsx +++ b/packages/x-charts/src/hooks/useSvgRef.test.tsx @@ -26,17 +26,24 @@ describe('useSvgRef', () => { ]); }); - it('should not throw an error when parent context is present', () => { - const ref = React.createRef(); - // @ts-expect-error, we don't need to create an actual SVG element - ref.current = { id: 'test-id' } as SVGSVGElement; - - const { getByText } = render( - - - , - ); - - expect(getByText('test-id')).toBeVisible(); + it('should not throw an error when parent context is present', async () => { + function RenderDrawingProvider() { + const ref = React.useRef(null); + + return ( + + + + + + ); + } + + const { findByText, forceUpdate } = render(); + + // Ref is not available on first render. + forceUpdate(); + + expect(await findByText('test-id')).toBeVisible(); }); }); diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index ff1d491adee3..d66579a4b534 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -2,9 +2,9 @@ import * as React from 'react'; import { SvgContext } from '../context/DrawingProvider'; export function useSvgRef(): React.MutableRefObject { - const svgRef = React.useContext(SvgContext); + const { isInitialized, svg } = React.useContext(SvgContext); - if (svgRef.current === null) { + if (!isInitialized) { throw new Error( [ 'MUI X: Could not find the svg ref context.', @@ -13,5 +13,5 @@ export function useSvgRef(): React.MutableRefObject { ); } - return svgRef as React.MutableRefObject; + return svg as React.MutableRefObject; } From f2782ce1c09aa457bad2255ac5a0dc88229b6477 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 5 Jun 2024 01:34:15 +0200 Subject: [PATCH 5/8] Fix karma tests --- .../HighlightedProvider/HighlightedContext.ts | 4 ++-- .../HighlightedProvider/useHighlighted.test.tsx | 17 +++++++++++++++-- packages/x-charts/src/hooks/useSeries.test.tsx | 17 +++++++++++++++-- packages/x-charts/src/hooks/useSvgRef.test.tsx | 17 +++++++++++++++-- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts b/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts index 1c512038a940..219b8e7236a6 100644 --- a/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts +++ b/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts @@ -60,14 +60,14 @@ export type HighlightScope = { fade?: FadeOptions; }; -export interface HighlightedState { +export type HighlightedState = { highlightScope?: Partial; highlightedItem: HighlightItemData | null; setHighlighted: (item: HighlightItemData) => void; clearHighlighted: () => void; isHighlighted: (input: HighlightItemData) => boolean; isFaded: (input: HighlightItemData) => boolean; -} +}; export const HighlightedContext = React.createContext>({ isInitialized: false, diff --git a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx index b1a17352afa2..03812aae6959 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx +++ b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.test.tsx @@ -13,10 +13,18 @@ function UseHighlighted() { describe('useHighlighted', () => { const { render } = createRenderer(); - it('should throw an error when parent context not present', () => { + it('should throw an error when parent context not present', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + // can't catch render errors in the browser for unknown reason + // tried try-catch + error boundary + window onError preventDefault + this.skip(); + } + + const errorRef = React.createRef(); + expect(() => render( - + , ), @@ -25,6 +33,11 @@ describe('useHighlighted', () => { 'It looks like you rendered your component outside of a ChartsContainer parent component.', 'The above error occurred in the component:', ]); + + expect((errorRef.current as any).errors).to.have.length(1); + expect((errorRef.current as any).errors[0].toString()).to.include( + 'MUI X: Could not find the highlighted ref context.', + ); }); it('should not throw an error when parent context is present', () => { diff --git a/packages/x-charts/src/hooks/useSeries.test.tsx b/packages/x-charts/src/hooks/useSeries.test.tsx index 41184514326d..392bece9582b 100644 --- a/packages/x-charts/src/hooks/useSeries.test.tsx +++ b/packages/x-charts/src/hooks/useSeries.test.tsx @@ -12,10 +12,18 @@ function UseSeries() { describe('useSeries', () => { const { render } = createRenderer(); - it('should throw an error when parent context not present', () => { + it('should throw an error when parent context not present', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + // can't catch render errors in the browser for unknown reason + // tried try-catch + error boundary + window onError preventDefault + this.skip(); + } + + const errorRef = React.createRef(); + expect(() => render( - + , ), @@ -24,6 +32,11 @@ describe('useSeries', () => { 'It looks like you rendered your component outside of a ChartsContainer parent component.', 'The above error occurred in the component:', ]); + + expect((errorRef.current as any).errors).to.have.length(1); + expect((errorRef.current as any).errors[0].toString()).to.include( + 'MUI X: Could not find the series ref context.', + ); }); it('should not throw an error when parent context is present', () => { diff --git a/packages/x-charts/src/hooks/useSvgRef.test.tsx b/packages/x-charts/src/hooks/useSvgRef.test.tsx index 5f74f1217442..a61113fa1e8d 100644 --- a/packages/x-charts/src/hooks/useSvgRef.test.tsx +++ b/packages/x-charts/src/hooks/useSvgRef.test.tsx @@ -12,10 +12,18 @@ function UseSvgRef() { describe('useSvgRef', () => { const { render } = createRenderer(); - it('should throw an error when parent context not present', () => { + it('should throw an error when parent context not present', function test() { + if (!/jsdom/.test(window.navigator.userAgent)) { + // can't catch render errors in the browser for unknown reason + // tried try-catch + error boundary + window onError preventDefault + this.skip(); + } + + const errorRef = React.createRef(); + expect(() => render( - + , ), @@ -24,6 +32,11 @@ describe('useSvgRef', () => { 'It looks like you rendered your component outside of a ChartsContainer parent component.', 'The above error occurred in the component:', ]); + + expect((errorRef.current as any).errors).to.have.length(1); + expect((errorRef.current as any).errors[0].toString()).to.include( + 'MUI X: Could not find the svg ref context.', + ); }); it('should not throw an error when parent context is present', async () => { From e1f612d4dd40ac3632da4f667c865a689561e364 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 5 Jun 2024 10:41:20 +0200 Subject: [PATCH 6/8] Add data as a prop on the root of initializable context --- .../x-charts/src/context/DrawingProvider.tsx | 8 +++---- .../HighlightedProvider/HighlightedContext.ts | 12 ++++++---- .../HighlightedProvider.tsx | 24 ++++++++++--------- .../HighlightedProvider/useHighlighted.ts | 4 ++-- .../src/context/SeriesContextProvider.tsx | 3 ++- .../x-charts/src/context/context.types.ts | 3 ++- packages/x-charts/src/hooks/useSeries.ts | 4 ++-- packages/x-charts/src/hooks/useSvgRef.ts | 4 ++-- 8 files changed, 33 insertions(+), 29 deletions(-) diff --git a/packages/x-charts/src/context/DrawingProvider.tsx b/packages/x-charts/src/context/DrawingProvider.tsx index 783354240942..6e7a5ceb6111 100644 --- a/packages/x-charts/src/context/DrawingProvider.tsx +++ b/packages/x-charts/src/context/DrawingProvider.tsx @@ -60,13 +60,11 @@ if (process.env.NODE_ENV !== 'production') { DrawingContext.displayName = 'DrawingContext'; } -export type SvgContextState = { - svg: React.RefObject; -}; +export type SvgContextState = React.RefObject; export const SvgContext = React.createContext>({ isInitialized: false, - svg: { current: null }, + data: { current: null }, }); if (process.env.NODE_ENV !== 'production') { @@ -83,7 +81,7 @@ export function DrawingProvider(props: DrawingProviderProps) { [chartId, drawingArea], ); - const refValue = React.useMemo(() => ({ isInitialized: true, svg: svgRef }), [svgRef]); + const refValue = React.useMemo(() => ({ isInitialized: true, data: svgRef }), [svgRef]); return ( diff --git a/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts b/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts index 219b8e7236a6..335b8ba59223 100644 --- a/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts +++ b/packages/x-charts/src/context/HighlightedProvider/HighlightedContext.ts @@ -71,11 +71,13 @@ export type HighlightedState = { export const HighlightedContext = React.createContext>({ isInitialized: false, - highlightedItem: null, - setHighlighted: () => {}, - clearHighlighted: () => {}, - isHighlighted: () => false, - isFaded: () => false, + data: { + highlightedItem: null, + setHighlighted: () => {}, + clearHighlighted: () => {}, + isHighlighted: () => false, + isFaded: () => false, + }, }); if (process.env.NODE_ENV !== 'production') { diff --git a/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx b/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx index eb7518e892ab..d9922f67bf9d 100644 --- a/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx +++ b/packages/x-charts/src/context/HighlightedProvider/HighlightedProvider.tsx @@ -71,18 +71,20 @@ function HighlightedProvider({ const providerValue = React.useMemo>(() => { return { isInitialized: true, - highlightScope, - highlightedItem, - setHighlighted: (itemData) => { - setHighlightedItem(itemData); - onHighlightChange?.(itemData); + data: { + highlightScope, + highlightedItem, + setHighlighted: (itemData) => { + setHighlightedItem(itemData); + onHighlightChange?.(itemData); + }, + clearHighlighted: () => { + setHighlightedItem(null); + onHighlightChange?.(null); + }, + isHighlighted: createIsHighlighted(highlightScope, highlightedItem), + isFaded: createIsFaded(highlightScope, highlightedItem), }, - clearHighlighted: () => { - setHighlightedItem(null); - onHighlightChange?.(null); - }, - isHighlighted: createIsHighlighted(highlightScope, highlightedItem), - isFaded: createIsFaded(highlightScope, highlightedItem), }; }, [highlightedItem, highlightScope, setHighlightedItem, onHighlightChange]); diff --git a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts index 7386192c3eaf..59e0c8b9ac27 100644 --- a/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts +++ b/packages/x-charts/src/context/HighlightedProvider/useHighlighted.ts @@ -9,7 +9,7 @@ import { HighlightedContext, HighlightedState } from './HighlightedContext'; * @returns {HighlightedState} the state of the chart */ export function useHighlighted(): HighlightedState { - const { isInitialized, ...highlighted } = React.useContext(HighlightedContext); + const { isInitialized, data } = React.useContext(HighlightedContext); if (!isInitialized) { throw new Error( @@ -20,5 +20,5 @@ export function useHighlighted(): HighlightedState { ); } - return highlighted; + return data; } diff --git a/packages/x-charts/src/context/SeriesContextProvider.tsx b/packages/x-charts/src/context/SeriesContextProvider.tsx index eed7e26e9f9c..63a3055fecb3 100644 --- a/packages/x-charts/src/context/SeriesContextProvider.tsx +++ b/packages/x-charts/src/context/SeriesContextProvider.tsx @@ -35,6 +35,7 @@ export type FormattedSeries = { [type in ChartSeriesType]?: FormatterResult>({ isInitialized: false, + data: {}, }); if (process.env.NODE_ENV !== 'production') { @@ -98,7 +99,7 @@ function SeriesContextProvider(props: SeriesContextProviderProps) { const formattedSeries = React.useMemo( () => ({ isInitialized: true, - ...formatSeries( + data: formatSeries( series, typeof colors === 'function' ? colors(theme.palette.mode) : colors, dataset as DatasetType, diff --git a/packages/x-charts/src/context/context.types.ts b/packages/x-charts/src/context/context.types.ts index 12a19a8720ad..16af92f28381 100644 --- a/packages/x-charts/src/context/context.types.ts +++ b/packages/x-charts/src/context/context.types.ts @@ -1,3 +1,4 @@ export type Initializable = { isInitialized: boolean; -} & T; + data: T; +}; diff --git a/packages/x-charts/src/hooks/useSeries.ts b/packages/x-charts/src/hooks/useSeries.ts index 2c3ed4d314e9..4b4d7fa6e079 100644 --- a/packages/x-charts/src/hooks/useSeries.ts +++ b/packages/x-charts/src/hooks/useSeries.ts @@ -8,7 +8,7 @@ import { FormattedSeries, SeriesContext } from '../context/SeriesContextProvider * @returns FormattedSeries series */ export function useSeries(): FormattedSeries { - const { isInitialized, ...series } = React.useContext(SeriesContext); + const { isInitialized, data } = React.useContext(SeriesContext); if (!isInitialized) { throw new Error( @@ -19,7 +19,7 @@ export function useSeries(): FormattedSeries { ); } - return series; + return data; } /** diff --git a/packages/x-charts/src/hooks/useSvgRef.ts b/packages/x-charts/src/hooks/useSvgRef.ts index d66579a4b534..d2540807afa6 100644 --- a/packages/x-charts/src/hooks/useSvgRef.ts +++ b/packages/x-charts/src/hooks/useSvgRef.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { SvgContext } from '../context/DrawingProvider'; export function useSvgRef(): React.MutableRefObject { - const { isInitialized, svg } = React.useContext(SvgContext); + const { isInitialized, data } = React.useContext(SvgContext); if (!isInitialized) { throw new Error( @@ -13,5 +13,5 @@ export function useSvgRef(): React.MutableRefObject { ); } - return svg as React.MutableRefObject; + return data as React.MutableRefObject; } From fd66249a40b73829104983d579d3c03cda79bca8 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 5 Jun 2024 10:48:20 +0200 Subject: [PATCH 7/8] trigger ci From 78a904f66bfcf50812c7c3dc27457a02827a06b3 Mon Sep 17 00:00:00 2001 From: Jose Quintas Date: Wed, 5 Jun 2024 11:22:30 +0200 Subject: [PATCH 8/8] Fix interaction highlighted import --- packages/x-charts/src/hooks/useInteractionItemProps.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/x-charts/src/hooks/useInteractionItemProps.ts b/packages/x-charts/src/hooks/useInteractionItemProps.ts index 633944cdfd2d..07d9dc7dccbd 100644 --- a/packages/x-charts/src/hooks/useInteractionItemProps.ts +++ b/packages/x-charts/src/hooks/useInteractionItemProps.ts @@ -1,11 +1,11 @@ import * as React from 'react'; import { InteractionContext } from '../context/InteractionProvider'; import { SeriesItemIdentifier } from '../models'; -import { HighlightedContext } from '../context'; +import { useHighlighted } from '../context'; export const useInteractionItemProps = (skip?: boolean) => { const { dispatch: dispatchInteraction } = React.useContext(InteractionContext); - const { setHighlighted, clearHighlighted } = React.useContext(HighlightedContext); + const { setHighlighted, clearHighlighted } = useHighlighted(); if (skip) { return () => ({});