Description
A race condition where a chart mounts/unmounts too fast can lead to a TypeError
StackTrace
TypeError: Cannot read properties of null (reading 'getAttribute')
at getAttribute (../../node_modules/echarts/lib/util/model.js:639:14)
at getInstanceByDom (../../node_modules/echarts/lib/core/echarts.js:2113:20)
at EChartsReactCore.prototype.getEchartsInstance (../../node_modules/echarts-for-react/esm/core.js:93:29)
at EChartsReactCore.prototype.updateEChartsOption (../../node_modules/echarts-for-react/esm/core.js:183:35)
at t.<anonymous> (../../node_modules/echarts-for-react/esm/core.js:126:48)
at step (../../node_modules/tslib/tslib.es6.mjs:147:21)
at Object.next (../../node_modules/tslib/tslib.es6.mjs:128:51)
at fulfilled (../../node_modules/tslib/tslib.es6.mjs:118:56)
My findings
I believe the bug happens in initEchartsInstance because the echart initialization can be too slow. By the time we get it, it might already be unmounted, leading to null.
public async initEchartsInstance(): Promise<ECharts> {
return new Promise((resolve) => {
// create temporary echart instance
this.echarts.init(this.ele, this.props.theme, this.props.opts);
const echartsInstance = this.getEchartsInstance(); // <-- HERE
echartsInstance.on('finished', () => {...}
To confirm my theory, I added an artificial 5-second timeout between the init and the getter and was able to reproduce the error 100% of the time
public async initEchartsInstance(): Promise<ECharts> {
// create temporary echart instance
this.echarts.init(this.ele, this.props.theme, this.props.opts);
// add an artificial 5 second timeout
await new Promise((resolve) => setTimeout(resolve, 5000));
return new Promise((resolve) => {
const echartsInstance = this.getEchartsInstance();
echartsInstance.on('finished', () => {...}
Description
A race condition where a chart mounts/unmounts too fast can lead to a TypeError
StackTrace
My findings
I believe the bug happens in
initEchartsInstancebecause the echart initialization can be too slow. By the time we get it, it might already be unmounted, leading to null.To confirm my theory, I added an artificial 5-second timeout between the init and the getter and was able to reproduce the error 100% of the time