我正在尝试使用C3在我的React项目中绘制图表。
我要做的是动态生成一个id(UUID),并将其附加到图表组件中的div
上。然后,在组件以componentDidMount
呈现之后,我将调用一些代码。这是一种常见的模式,我在其他项目中也看到过。
起初,一切似乎都很好。但是,在反复刷新页面后,有时无法生成图表。我得到的错误是:
DOMException: Failed to execute 'querySelector' on 'Document': '#a-really-long-id' is not a valid selector.
我尝试使用setTimeout
来延迟图表的添加时间,但是奇怪的是,即使延迟了10秒,我仍然得到相同的结果。这使我相信这不是比赛条件,是由其他原因引起的。也许C3读取DOM一次并且不响应更改?但这并不能解释为什么有时...
即使尝试从Chrome开发者控制台中按ID选择元素,也行不通。
这是我的完整组件代码:
// assets/js/index.jsx
import React from 'react';
import uuid from 'uuid/v4';
import c3 from 'c3';
class Chart extends React.Component {
constructor(props) {
super(props);
this.id = uuid();
this._update = this._update.bind(this);
}
_update() {
const data = this.props.data;
this.chart = c3.generate({
bindto: `#${this.id}`,
data: {
columns: [
['Male', 0],
['Female', 0],
['Brand', 0]
],
type: 'bar',
colors: {
Male: '#0066CC',
Female: '#FF6666',
Brand: '#808080'
},
groups: [
['Male', 'Female', 'Brand']
],
order: null
},
bar: {
width: {
ratio: 0.3
}
},
transition: {
duration: 500
},
tooltip: {
show: false
},
axis: {
x: { show: false },
y: { show: false },
},
size: { width: 220, height: 320 },
grid: {
x: { show: false }
},
legend: {
show: false
}
});
setTimeout(function() {
this.chart.load({
columns: [
['Male', data.male],
['Female', data.female],
['Brand', data.brand]
]
});
}, 500);
}
componentDidMount() {
this._update();
}
render() {
return (
<div id={this.id} className="chart"></div>
);
}
}
export default Chart;
答案 0 :(得分:1)
可以将其添加为注释,但由于注释很大,因此将其添加为答案。
您是否使用html4 / html5语义?
按照HTML4(https://www.w3.org/TR/html401/types.html)
ID和NAME令牌必须以字母([A-Za-z])开头,并且可以是 后跟任意数量的字母,数字([0-9]),连字符(“-”), 下划线(“ _”),冒号(“:”)和句点(“。”)。
按照HTML5(https://www.w3.org/TR/html5/dom.html)
在HTML元素上指定时,id属性值必须唯一 在元素树的所有ID中,并且必须至少包含 一个字符。该值不得包含任何空格字符。
您的uuid有时可能会生成一个有效的ID,有时可能会生成一个有效的ID(不确定uuid的工作方式)
如果您不使用HTML5语义,则只需添加<!DOCTYPE html>
并尝试一下。
还
您在逻辑中使用了settimeout,并在其中使用了this。图
this
,现在将引用settimeout而不是类。
您可以尝试更改
setTimeout(function() {
this.chart.load({
columns: [
['Male', data.male],
['Female', data.female],
['Brand', data.brand]
]
});
}, 500);
到
setTimeout( () => {
this.chart.load({
columns: [
['Male', data.male],
['Female', data.female],
['Brand', data.brand]
]
});
}, 500);