@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
import Chart from 'chart.js' ;
4
4
import isEqual from 'lodash/isEqual' ;
5
5
import find from 'lodash/find' ;
6
-
6
+ import keyBy from 'lodash/keyBy' ;
7
7
8
8
class ChartComponent extends React . Component {
9
9
static getLabelAsKey = d => d . label ;
@@ -160,36 +160,35 @@ class ChartComponent extends React.Component {
160
160
let currentDatasets = ( this . chartInstance . config . data && this . chartInstance . config . data . datasets ) || [ ] ;
161
161
const nextDatasets = data . datasets || [ ] ;
162
162
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
+ } ;
174
187
} 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 ;
189
189
}
190
- }
191
- // finally add any new series
192
- newDatasets . forEach ( d => currentDatasets . push ( d ) ) ;
190
+ } ) ;
191
+
193
192
const { datasets, ...rest } = data ;
194
193
195
194
this . chartInstance . config . data = {
0 commit comments