Skip to content

Commit 81014c8

Browse files
committed
Improve update of datasets to use correct dataset order
1 parent c3521a9 commit 81014c8

File tree

1 file changed

+28
-29
lines changed

1 file changed

+28
-29
lines changed

src/index.js

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
33
import Chart from 'chart.js';
44
import isEqual from 'lodash/isEqual';
55
import find from 'lodash/find';
6-
6+
import keyBy from 'lodash/keyBy';
77

88
class ChartComponent extends React.Component {
99
static getLabelAsKey = d => d.label;
@@ -160,36 +160,35 @@ class ChartComponent extends React.Component {
160160
let currentDatasets = (this.chartInstance.config.data && this.chartInstance.config.data.datasets) || [];
161161
const nextDatasets = data.datasets || [];
162162

163-
// use the key provider to work out which series have been added/removed/changed
164-
const currentDatasetKeys = currentDatasets.map(this.props.datasetKeyProvider);
165-
const nextDatasetKeys = nextDatasets.map(this.props.datasetKeyProvider);
166-
const newDatasets = nextDatasets.filter(d => currentDatasetKeys.indexOf(this.props.datasetKeyProvider(d)) === -1);
167-
168-
// process the updates (via a reverse for loop so we can safely splice deleted datasets out of the array
169-
for (let idx = currentDatasets.length - 1; idx >= 0; idx -= 1) {
170-
const currentDatasetKey = this.props.datasetKeyProvider(currentDatasets[idx]);
171-
if (nextDatasetKeys.indexOf(currentDatasetKey) === -1) {
172-
// deleted series
173-
currentDatasets.splice(idx, 1);
163+
const currentDatasetsIndexed = keyBy(
164+
currentDatasets,
165+
this.props.datasetKeyProvider
166+
);
167+
168+
// We can safely replace the dataset array, as long as we retain the _meta property
169+
// on each dataset.
170+
this.chartInstance.config.data.datasets = nextDatasets.map(next => {
171+
const current =
172+
currentDatasetsIndexed[this.props.datasetKeyProvider(next)];
173+
if (current && current.type === next.type) {
174+
// The data array must be edited in place. As chart.js adds listeners to it.
175+
current.data.splice(next.data.length);
176+
next.data.forEach((point, pid) => {
177+
current.data[pid] = next.data[pid];
178+
});
179+
const { data, ...otherProps } = next;
180+
// Merge properties. Notice a weakness here. If a property is removed
181+
// from next, it will be retained by current and never disappears.
182+
// Workaround is to set value to null or undefined in next.
183+
return {
184+
...current,
185+
...otherProps
186+
};
174187
} else {
175-
const retainedDataset = find(nextDatasets, d => this.props.datasetKeyProvider(d) === currentDatasetKey);
176-
if (retainedDataset) {
177-
// update it in place if it is a retained dataset
178-
currentDatasets[idx].data.splice(retainedDataset.data.length);
179-
retainedDataset.data.forEach((point, pid) => {
180-
currentDatasets[idx].data[pid] = retainedDataset.data[pid];
181-
});
182-
const {data, ...otherProps} = retainedDataset;
183-
currentDatasets[idx] = {
184-
data: currentDatasets[idx].data,
185-
...currentDatasets[idx],
186-
...otherProps
187-
};
188-
}
188+
return next;
189189
}
190-
}
191-
// finally add any new series
192-
newDatasets.forEach(d => currentDatasets.push(d));
190+
});
191+
193192
const { datasets, ...rest } = data;
194193

195194
this.chartInstance.config.data = {

0 commit comments

Comments
 (0)