Skip to content

Commit f895766

Browse files
authored
feat: datasetIdKey prop (#848)
datasetIdKey prop added to track datasets changes
1 parent 6a9b2a7 commit f895766

File tree

5 files changed

+85
-9
lines changed

5 files changed

+85
-9
lines changed

Diff for: .size-limit

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[
22
{
33
"path": "dist/index.cjs",
4-
"limit": "1.6 KB",
4+
"limit": "1.7 KB",
55
"webpack": false,
66
"running": false
77
},

Diff for: src/chart.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ function ChartComponent<
2121
height = 150,
2222
width = 300,
2323
redraw = false,
24+
datasetIdKey,
2425
type,
2526
data,
2627
options,
@@ -40,7 +41,7 @@ function ChartComponent<
4041

4142
chartRef.current = new ChartJS(canvasRef.current, {
4243
type,
43-
data: cloneData(data),
44+
data: cloneData(data, datasetIdKey),
4445
options,
4546
plugins,
4647
});
@@ -71,7 +72,7 @@ function ChartComponent<
7172

7273
useEffect(() => {
7374
if (!redraw && chartRef.current && data.datasets) {
74-
setDatasets(chartRef.current.config.data, data.datasets);
75+
setDatasets(chartRef.current.config.data, data.datasets, datasetIdKey);
7576
}
7677
}, [redraw, data.datasets]);
7778

Diff for: src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface ChartProps<
1818
options?: ChartOptions<TType>;
1919
plugins?: Plugin<TType>[];
2020
redraw?: boolean;
21+
datasetIdKey?: string;
2122
/**
2223
* @todo Replace with `children` prop.
2324
*/

Diff for: src/utils.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import type {
88
Chart,
99
} from 'chart.js';
1010

11+
const defaultDatasetIdKey = 'label';
12+
1113
export function reforwardRef<T>(ref: ForwardedRef<T>, value: T) {
1214
if (typeof ref === 'function') {
1315
ref(value);
@@ -41,17 +43,27 @@ export function setDatasets<
4143
TLabel = unknown
4244
>(
4345
currentData: ChartData<TType, TData, TLabel>,
44-
nextDatasets: ChartDataset<TType, TData>[]
46+
nextDatasets: ChartDataset<TType, TData>[],
47+
datasetIdKey = defaultDatasetIdKey
4548
) {
49+
const addedDatasets: ChartDataset<TType, TData>[] = [];
50+
4651
currentData.datasets = nextDatasets.map(nextDataset => {
4752
// given the new set, find it's current match
4853
const currentDataset = currentData.datasets.find(
49-
dataset =>
50-
dataset.label === nextDataset.label && dataset.type === nextDataset.type
54+
dataset => dataset[datasetIdKey] === nextDataset[datasetIdKey]
5155
);
5256

5357
// There is no original to update, so simply add new one
54-
if (!currentDataset || !nextDataset.data) return { ...nextDataset };
58+
if (
59+
!currentDataset ||
60+
!nextDataset.data ||
61+
addedDatasets.includes(currentDataset)
62+
) {
63+
return { ...nextDataset };
64+
}
65+
66+
addedDatasets.push(currentDataset);
5567

5668
Object.assign(currentDataset, nextDataset);
5769

@@ -63,14 +75,14 @@ export function cloneData<
6375
TType extends ChartType = ChartType,
6476
TData = DefaultDataPoint<TType>,
6577
TLabel = unknown
66-
>(data: ChartData<TType, TData, TLabel>) {
78+
>(data: ChartData<TType, TData, TLabel>, datasetIdKey = defaultDatasetIdKey) {
6779
const nextData: ChartData<TType, TData, TLabel> = {
6880
labels: [],
6981
datasets: [],
7082
};
7183

7284
setLabels(nextData, data.labels);
73-
setDatasets(nextData, data.datasets);
85+
setDatasets(nextData, data.datasets, datasetIdKey);
7486

7587
return nextData;
7688
}

Diff for: test/chart.test.tsx

+62
Original file line numberDiff line numberDiff line change
@@ -324,4 +324,66 @@ describe('<Chart />', () => {
324324

325325
expect(chart.canvas.getAttribute('aria-label')).toBe(ariaLabel);
326326
});
327+
328+
it('should rerender datasets with same labels', () => {
329+
const getData = () => ({
330+
labels: [1, 2, 3],
331+
datasets: [
332+
{
333+
label: '',
334+
data: [5, 6, 7],
335+
},
336+
{
337+
label: '',
338+
data: [3, 2, 1],
339+
},
340+
],
341+
});
342+
343+
const { rerender } = render(
344+
<Chart ref={ref} type='line' data={getData()} />
345+
);
346+
347+
const [prevDataset1, prevDataset2] = chart.config.data.datasets;
348+
349+
rerender(<Chart ref={ref} type='line' data={getData()} />);
350+
351+
const [nextDataset1, nextDataset2] = chart.config.data.datasets;
352+
353+
expect(prevDataset1).toBe(nextDataset1);
354+
expect(prevDataset2).not.toBe(nextDataset2);
355+
});
356+
357+
it('should rerender datasets with id', () => {
358+
const getData = () => ({
359+
labels: [1, 2, 3],
360+
datasets: [
361+
{
362+
id: 1,
363+
label: '',
364+
data: [5, 6, 7],
365+
},
366+
{
367+
id: 2,
368+
label: '',
369+
data: [3, 2, 1],
370+
},
371+
],
372+
});
373+
374+
const { rerender } = render(
375+
<Chart ref={ref} datasetIdKey='id' type='line' data={getData()} />
376+
);
377+
378+
const [prevDataset1, prevDataset2] = chart.config.data.datasets;
379+
380+
rerender(
381+
<Chart ref={ref} datasetIdKey='id' type='line' data={getData()} />
382+
);
383+
384+
const [nextDataset1, nextDataset2] = chart.config.data.datasets;
385+
386+
expect(prevDataset1).toBe(nextDataset1);
387+
expect(prevDataset2).toBe(nextDataset2);
388+
});
327389
});

0 commit comments

Comments
 (0)