C3 和 React - DOMException

C3 and React - DOMException

我正在尝试使用 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 select 元素也没有用。

代码

这是我的完整组件代码:

// 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;

这可以添加为评论,但由于它很大,所以将其添加为答案。

你在使用 html4/html5 语义吗?

根据 HTML4 (https://www.w3.org/TR/html401/types.html)

ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").

根据 HTML5 (https://www.w3.org/TR/html5/dom.html)

When specified on HTML elements, the id attribute value must be unique amongst all the IDs in the element’s tree and must contain at least one character. The value must not contain any space characters.

您的 uuid 有时可能会生成有效 ID,有时可能不会(不确定 uuid 是如何工作的)

如果你不使用HTML5语义,你可以简单地添加<!DOCTYPE html>

在您的 html 文档的顶部尝试一下。

此外,

您在逻辑中使用了 settimeout,并在其中使用了 this.Chart

this,现在将引用 settimeout 而不是 class。

你能试着改变一下吗

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);