【问题标题】:React + nvd3: 'querySelector' of undefined while running sample codeReact + nvd3:运行示例代码时未定义的'querySelector'
【发布时间】:2017-12-21 22:20:43
【问题描述】:

我正在尝试将nvd3react 集成。当我刷新页面时,node.js 失败并出现以下错误:

/home/nikita/project/node_modules/d3/d3.js:562 返回 n.querySelector(s); ^

TypeError: 无法读取未定义的属性“querySelector”

我在没有react 的情况下测试了nvd3 代码,当它显示为html 文件并且工作正常时,但现在我想将它与react 集成并使用.jsx 文件作为视图代替平原html。呈现的文件如下:

import React from 'react';
import DefaultLayout from './layouts/default';
import * as d3 from "d3";
import nvd3 from "nvd3";
require("./barChart.js");

class Index extends React.Component {
  render() {
    return (
      <DefaultLayout title={this.props.title}>
        <div>Hello {this.props.name}</div>
        <div id="barChart">
            <svg styles={{height:'600px'}}/>
        </div>
      </DefaultLayout>
    );
  }
}

module.exports = Index;

barChart.js 看起来像这样:

import * as d3 from "d3";
import nvd3 from "nvd3";
var nv = nvd3;

 var barChart = nv.addGraph(function() {
        var chart = nv.models.discreteBarChart()
        .x(function(d) { return d.label })
        .y(function(d) { return d.value })
        .staggerLabels(true)
        //.staggerLabels(historicalBarChart[0].values.length > 8)
        .showValues(true)
        .duration(250)
        ;
    d3.select('#barChart svg')
        .datum(exampleData)
        .call(chart);
    nv.utils.windowResize(chart.update);
    return chart;
});

//Each bar represents a single discrete quantity.
function exampleData() {
 return  [
{
  key: "Cumulative Return",
  values: [
    {
      "label" : "A Label" ,
      "value" : -29.765957771107
    } ,
    {
      "label" : "B Label" ,
      "value" : 0
    } ,
    {
      "label" : "C Label" ,
      "value" : 32.807804682612
    } ,
    {
      "label" : "D Label" ,
      "value" : 196.45946739256
    } ,
    {
      "label" : "E Label" ,
      "value" : 0.19434030906893
    } ,
    {
      "label" : "F Label" ,
      "value" : -98.079782601442
    } ,
    {
      "label" : "G Label" ,
      "value" : -13.925743130903
    } ,
    {
      "label" : "H Label" ,
      "value" : -5.1387322875705
    }
  ]
}
  ]

}

module.exports = barChart

另外,package.json:

"dependencies": {
"babel-preset-env": "^1.6.1",
"body-parser": "~1.18.2",
"cookie-parser": "~1.4.3",
"d3": "^3.5.17",
"debug": "~2.6.9",
"express": "~4.15.5",
"express-react-views": "^0.10.4",
"mongodb": "^2.2.25",
"monk": "^4.0.0",
"morgan": "~1.9.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-nvd3": "^0.5.7",
"serve-favicon": "~2.4.5"
},

我尝试重写barChart.js,如教程中所示:https://medium.com/@Elijah_Meeks/interactive-applications-with-react-d3-f76f7b3ebc71 但没有成功。可以消除该错误,但问题的根本原因 - nvd3 错误选择了 DOM 元素 - 尚未解决。

【问题讨论】:

  • 在 react 中使用 id 是不行的,原因是虚拟 DOM 的渲染以及与真实 DOM 的比较,如果您从 reactjs 外部操作 dom,将会搞砸渲染,除此之外,react 还会创建自己的 id 以使比较更轻松。想办法解决它,检查ref回调是否可以帮助你
  • 什么是ref 回调?对不起,我是新来的反应
  • 您可以在reactjs.org/docs/refs-and-the-dom.html这里的文档中查找它,基本上是通过ref,您可以保存渲染的组件,以便稍后进行一些基本操作
  • 好的,谢谢。我尝试使用class 属性进行d3 选择,但它并没有解决问题
  • 何时执行您的条形图的回调?请注意,如果我没看错,您的组件可能不会在您需要条形图时呈现,但我并没有真正看到您在哪里调用它

标签: javascript reactjs d3.js nvd3.js


【解决方案1】:

按照icepickle 的建议在React 中使用refs 而不是id 并使用教程:

https://medium.com/@Elijah_Meeks/interactive-applications-with-react-d3-f76f7b3ebc71

我通过以下方式更改了barChart.js

import React, { Component } from 'react'
import * as d3 from "d3";
import nvd3 from "nvd3";
var nv = nvd3;

class barChart extends Component {
  constructor(props){
      super(props)
      this.createBarChart = this.createBarChart.bind(this)
  }

  componentDidMount() {
     this.createBarChart()
  }

  componentDidUpdate() {
    this.createBarChart()
  }

  createBarChart() {
    const node = this.node
    nv.addGraph(function() {
     var chart = nv.models.discreteBarChart()
        .x(function(d) { return d.label })
        .y(function(d) { return d.value })
        .staggerLabels(true)
        //.staggerLabels(historicalBarChart[0].values.length > 8)
        .showValues(true)
        .duration(250)
        ;
    d3.select(node)
        .datum(exampleData)
        .call(chart);
    nv.utils.windowResize(chart.update);
    return chart;
});
//Each bar represents a single discrete quantity.
function exampleData() {
 return  [
    {
      key: "Cumulative Return",
      values: [
        {
          "label" : "A Label" ,
          "value" : -29.765957771107
        } ,
        {
          "label" : "B Label" ,
          "value" : 0
        } ,
        {
          "label" : "C Label" ,
          "value" : 32.807804682612
        } ,
        {
          "label" : "D Label" ,
          "value" : 196.45946739256
        } ,
        {
          "label" : "E Label" ,
          "value" : 0.19434030906893
        } ,
        {
          "label" : "F Label" ,
          "value" : -98.079782601442
        } ,
        {
          "label" : "G Label" ,
          "value" : -13.925743130903
        } ,
        {
          "label" : "H Label" ,
          "value" : -5.1387322875705
        }
      ]
    }
  ]

}
  }

  render() {
  return <svg ref={node => this.node = node}
  width={500} height={500}>
  </svg>
 }

}

export default barChart

并在Index.jsx主视图中使用了元素:

import React from 'react';
import DefaultLayout from './layouts/default';
import * as d3 from "d3";
import nvd3 from "nvd3";
import barChart from './barChart';

class Index extends React.Component {
  render() {
    return (
      <DefaultLayout title={this.props.title}>
          <div>Hello {this.props.name}</div>
        <div>
          <barChart/>
        </div>
      </DefaultLayout>
   );
 }
}

module.exports = Index;

错误消失了,节点没有失败,但是,由于某些其他原因,图表仍未呈现。在做了一些搜索之后,我意识到我的 React 入口点搞砸了:我认为该节点应该呈现 jsx 视图 index.jsx 并且应该这样做,但结果证明是非常错误的。

我需要将index.html 文件添加到我的public 节点静态资源文件夹中,然后创建一个新条目index.js 文件(我将index.jsx 重命名为App.jsx):

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App/>, document.getElementById('root'));

然后,我需要更正从小写 (app -&gt; App; barChart -&gt; BarChart) 开始的 react 模块的所有名称为大写:显然React 强制用户使用某些命名约定。

然后我安装了webpack,将所有.jsx文件捆绑到bundle.js,将其作为&lt;script&gt;标签导入index.html

只有在完成所有这些之后,项目才开始正常工作。

【讨论】:

  • 是的,组件和类的名称应该以大写开头,我会进一步重构并实现 componentShouldUpdate( nextProps ) 事件,以确保您的组件仅在 props 更改后重新呈现.在此之后,您的示例数据应该是 BarChart 组件上的一个道具,同样适用于任何可以被视为 BarChart 变量的东西,这样您就可以尽可能地重用该组件。另请注意,node 在您当前的代码中可以为空(例如:切换路由时或即将卸载之前)
猜你喜欢
  • 2015-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-30
  • 2016-11-08
  • 1970-01-01
相关资源
最近更新 更多