Skip to content

Commit a99556b

Browse files
BenLorantfyjerairrest
authored andcommitted
Output a warning whenever user tries to use datasets without a unique key (#135)
* Output a warning whenever user tries to use datasets without a unique key * grammar fix * only show warning in dev enviroment * Rebased, changed NODE_ENV to get from process.env, moved code to checkDatasets function * linting fixes
1 parent c7976a8 commit a99556b

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

src/index.js

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import isEqual from 'lodash/isEqual';
55
import find from 'lodash/find';
66
import keyBy from 'lodash/keyBy';
77

8+
const NODE_ENV = (typeof process !== 'undefined') && process.env && process.env.NODE_ENV;
9+
810
class ChartComponent extends React.Component {
911
static getLabelAsKey = d => d.label;
1012

@@ -144,6 +146,25 @@ class ChartComponent extends React.Component {
144146
return data;
145147
}
146148

149+
checkDatasets(datasets) {
150+
const isDev = NODE_ENV !== 'production' && NODE_ENV !== 'prod';
151+
const usingCustomKeyProvider = this.props.datasetKeyProvider !== ChartComponent.getLabelAsKey;
152+
const multipleDatasets = datasets.length > 1;
153+
154+
if (isDev && multipleDatasets && !usingCustomKeyProvider) {
155+
let shouldWarn = false;
156+
datasets.forEach((dataset) => {
157+
if (!dataset.label) {
158+
shouldWarn = true;
159+
}
160+
});
161+
162+
if (shouldWarn) {
163+
console.error('[react-chartjs-2] Warning: Each dataset needs a unique key. By default, the "label" property on each dataset is used. Alternatively, you may provide a "datasetKeyProvider" as a prop that returns a unique key.');
164+
}
165+
}
166+
}
167+
147168
updateChart() {
148169
const {options} = this.props;
149170

@@ -159,6 +180,7 @@ class ChartComponent extends React.Component {
159180
// seamless transitions
160181
let currentDatasets = (this.chartInstance.config.data && this.chartInstance.config.data.datasets) || [];
161182
const nextDatasets = data.datasets || [];
183+
this.checkDatasets(currentDatasets);
162184

163185
const currentDatasetsIndexed = keyBy(
164186
currentDatasets,
@@ -170,6 +192,7 @@ class ChartComponent extends React.Component {
170192
this.chartInstance.config.data.datasets = nextDatasets.map(next => {
171193
const current =
172194
currentDatasetsIndexed[this.props.datasetKeyProvider(next)];
195+
173196
if (current && current.type === next.type) {
174197
// The data array must be edited in place. As chart.js adds listeners to it.
175198
current.data.splice(next.data.length);
@@ -233,7 +256,7 @@ class ChartComponent extends React.Component {
233256
}
234257

235258
ref = (element) => {
236-
this.element = element
259+
this.element = element;
237260
}
238261

239262
render() {

test/__tests__/Chart_spec.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,79 @@ describe('<Chart />', () => {
222222
expect(dataFn.calledWith(canvas)).to.equal(true);
223223
});
224224
});
225+
226+
describe('checkDatasets', () => {
227+
let consoleStub = null;
228+
beforeEach(() => {
229+
consoleStub = sinon.stub(global.console, 'error');
230+
});
231+
232+
afterEach(() => {
233+
consoleStub.restore();
234+
consoleStub = null;
235+
});
236+
237+
it('should log error to console if datasets don\'t have a label', () => {
238+
const wrapper = mountComponent({ data: {} });
239+
wrapper.setProps({
240+
data: {
241+
datasets: [
242+
{
243+
_id: '238940890234809234',
244+
data: [10, 20, 10, 20, 10, 20, 10]
245+
},
246+
{
247+
_id: '098340598345839455',
248+
data: [50, 100, 50, 100, 50, 100, 50]
249+
}
250+
]
251+
}
252+
});
253+
wrapper.update();
254+
255+
expect(consoleStub.callCount).to.equal(1);
256+
});
257+
258+
it('should not log error to console if all datasets have a label', () => {
259+
const wrapper = mountComponent({ data: {} });
260+
wrapper.setProps({
261+
data: {
262+
datasets: [
263+
{
264+
label: 'My first dataset',
265+
data: [10, 20, 10, 20, 10, 20, 10]
266+
},
267+
{
268+
label: 'My second dataset',
269+
data: [50, 100, 50, 100, 50, 100, 50]
270+
}
271+
]
272+
}
273+
});
274+
wrapper.update();
275+
276+
expect(consoleStub.callCount).to.equal(0);
277+
});
278+
279+
it('should not log error to console if a custom datasetKeyProvider is provided', () => {
280+
const wrapper = mountComponent({ datasetKeyProvider: (d) => d._id });
281+
wrapper.setProps({
282+
data: {
283+
datasets: [
284+
{
285+
_id: '238940890234809234',
286+
data: [10, 20, 10, 20, 10, 20, 10]
287+
},
288+
{
289+
_id: '098340598345839455',
290+
data: [50, 100, 50, 100, 50, 100, 50]
291+
}
292+
]
293+
}
294+
});
295+
wrapper.update();
296+
297+
expect(consoleStub.callCount).to.equal(0);
298+
});
299+
});
225300
});

0 commit comments

Comments
 (0)