Thursday, September 14, 2017

D3 charts using React JS and Node JS error --element type is invalid: expected a string (for built-in components) or a class/function


From the last two months I am working on Big Data technologies like Hadoop, Python, Spark, Kafka
and web front end frameworks like Angular JS , React JS and D3 charts.

Our requirement is to Display Data from Hadoop as charts. Pyspark will load the data into DataFrame , then convert the DataFrame into JSON data, React with D3 charts will use this JSON data and display as charts on the portal.

used the below two commands to create a facebook provided sample React JS app.

npm install -g create-react-app
create-react-app AppName

I found one solution in git and modified the solution to make it a Node.JS solution, I have added import and require statements.

used npm install statements to install packages.

npm run build , to run the build and serve -s build to start the web application on localhost.

as I am learning react js, struggled for two days to make things happen. A silly mistake that I did is

to import components, we need to use {} brackets, if we omit these brackets, then it will not give any compilation error, but while running, you will get javascript error saying

"element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. check the render method of  'ComponentName'"

below is the working version of  the import statements in App.jsx

import React, {Component} from 'react'
import ReactDOM from 'react-dom';
import ReactD3 from 'react-d3-components';
import {Waveform} from 'react-d3-components'
import {BarChart} from 'react-d3-components'
import {PieChart} from 'react-d3-components'
import {AreaChart} from 'react-d3-components'
import {ScatterPlot} from 'react-d3-components'
import {LineChart} from 'react-d3-components'
import {Brush} from 'react-d3-components'

const d3 = require('d3');

index.json file contents

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


const  sw = require('./registerServiceWorker');

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


Below is the code to render D3 chart

render: function() {
  return (
    <div>
    <LineChart data={this.state.data}
                           width={400}
                           height={400}
                           margin={{top: 10, bottom: 50, left: 50, right: 20}}
                           xScale={this.state.xScale}
                           xAxis={{tickValues: this.state.xScale.ticks(d3.time.day, 2), tickFormat: d3.time.format("%m/%d")}}
        tooltipHtml={tooltipLine}
        />

    <div className="brush" style={{float: 'none' }}>
    <Brush width={400}
                       height={50}
                       margin={{top: 0, bottom: 30, left: 50, right: 20}}
                       xScale={this.state.xScaleBrush}
                       extent={[new Date(2015, 2, 10), new Date(2015, 2, 12)]}
                       onChange={this._onChange}
                       xAxis={{tickValues: this.state.xScaleBrush.ticks(d3.time.day, 2), tickFormat: d3.time.format("%m/%d")}}
        />
    </div>
    </div>
  );
 },
 _onChange: function(extent) {
  this.setState({xScale: d3.time.scale().domain([extent[0], extent[1]]).range([0, 400 - 70])});
 }
});
ReactDOM.render(
 <SomeComponent />,
 document.getElementById('brush')
 );