diff --git a/src/chart.tsx b/src/chart.tsx index 357890a5e..754178902 100644 --- a/src/chart.tsx +++ b/src/chart.tsx @@ -4,7 +4,13 @@ import ChartJS from 'chart.js/auto'; import type { ChartData, ChartType, DefaultDataPoint } from 'chart.js'; import type { Props, TypedChartComponent } from './types'; -import { reforwardRef, setNextDatasets } from './utils'; +import { + reforwardRef, + cloneData, + setOptions, + setLabels, + setDatasets, +} from './utils'; const noopData = { datasets: [], @@ -49,7 +55,7 @@ function ChartComponent< chartRef.current = new ChartJS(canvasRef.current, { type, - data, + data: cloneData(data), options, plugins, }); @@ -119,19 +125,19 @@ function ChartComponent< useEffect(() => { if (!redraw && chartRef.current && options) { - chartRef.current.options = { ...options }; + setOptions(chartRef.current, options); } }, [redraw, options]); useEffect(() => { if (!redraw && chartRef.current) { - chartRef.current.config.data.labels = data.labels; + setLabels(chartRef.current.config.data, data.labels); } }, [redraw, data.labels]); useEffect(() => { if (!redraw && chartRef.current && data.datasets) { - setNextDatasets(chartRef.current.config.data, data.datasets); + setDatasets(chartRef.current.config.data, data.datasets); } }, [redraw, data.datasets]); diff --git a/src/utils.ts b/src/utils.ts index 3b27bc49f..dd0303120 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,6 +4,8 @@ import type { ChartData, DefaultDataPoint, ChartDataset, + ChartOptions, + Chart, } from 'chart.js'; export function reforwardRef(ref: ForwardedRef, value: T) { @@ -14,7 +16,26 @@ export function reforwardRef(ref: ForwardedRef, value: T) { } } -export function setNextDatasets< +export function setOptions< + TType extends ChartType = ChartType, + TData = DefaultDataPoint, + TLabel = unknown +>(chart: Chart, nextOptions: ChartOptions) { + chart.options = { ...nextOptions }; +} + +export function setLabels< + TType extends ChartType = ChartType, + TData = DefaultDataPoint, + TLabel = unknown +>( + currentData: ChartData, + nextLabels: TLabel[] | undefined +) { + currentData.labels = nextLabels; +} + +export function setDatasets< TType extends ChartType = ChartType, TData = DefaultDataPoint, TLabel = unknown @@ -30,10 +51,26 @@ export function setNextDatasets< ); // There is no original to update, so simply add new one - if (!currentDataset || !nextDataset.data) return nextDataset; + if (!currentDataset || !nextDataset.data) return { ...nextDataset }; Object.assign(currentDataset, nextDataset); return currentDataset; }); } + +export function cloneData< + TType extends ChartType = ChartType, + TData = DefaultDataPoint, + TLabel = unknown +>(data: ChartData) { + const nextData: ChartData = { + labels: [], + datasets: [], + }; + + setLabels(nextData, data.labels); + setDatasets(nextData, data.datasets); + + return nextData; +} diff --git a/stories/Chart.data.ts b/stories/Chart.data.ts index 43e1cccfc..4b8dc7f22 100644 --- a/stories/Chart.data.ts +++ b/stories/Chart.data.ts @@ -108,3 +108,48 @@ export const eventsData = { }, ], }; + +export const sameData1 = { + labels: [ + 'Jan', + 'Feb', + 'Mar', + 'Apr', + 'Mei', + 'Jun', + 'Jul', + 'Aug', + 'Sep', + 'Oct', + 'Nov', + 'Dec', + ], + datasets: [ + { + label: 'My First dataset', + backgroundColor: 'rgba(75,192,192,0.4)', + data: [33, 53, 85, 41, 44, 65, 61, 47, 52, 53, 62, 82], + }, + { + label: 'My Second dataset', + backgroundColor: '#742774', + data: [33, 25, 35, 51, 54, 76, 65, 40, 42, 39, 51, 55], + }, + ], +}; + +export const sameData2 = { + labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + datasets: [ + { + label: 'My First dataset', + backgroundColor: 'rgba(75,192,192,0.4)', + data: [42, 13, 45, 29, 44, 25, 27], + }, + { + label: 'My Second dataset', + backgroundColor: '#742774', + data: [33, 25, 35, 44, 50, 40, 48], + }, + ], +}; diff --git a/stories/Chart.tsx b/stories/Chart.tsx index 01c401d71..b3a975d26 100644 --- a/stories/Chart.tsx +++ b/stories/Chart.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useReducer } from 'react'; import { InteractionItem } from 'chart.js'; import Chart from '../src'; import * as data from './Chart.data'; @@ -100,3 +100,17 @@ Redraw.args = { data: data.multiTypeData, redraw: true, }; + +export const SameDataToggle = args => { + const [currentData, toggleData] = useReducer( + prevState => + prevState === data.sameData1 ? data.sameData2 : data.sameData1, + data.sameData1 + ); + + return ; +}; + +SameDataToggle.args = { + type: 'bar', +};