reactjs / react-chartjs

common react charting components using chart.js
MIT License
2.93k stars 301 forks source link

intermediate value)[chartType] is not a function #112

Closed SylarRuby closed 8 years ago

SylarRuby commented 8 years ago

What am I doing wrong, guys?

var LineChart = require("react-chartjs");

var MyComponent = React.createClass({
  render() {
   var chartData = {

  };
    return <LineChart.Line data={chartData} width="600" height="250"/>
  }
});

Only to get:

intermediate value)[chartType] is not a function

Which is at:

 classData.initializeChart = function(nextProps) {
      var Chart = require('chart.js');
      var el = ReactDOM.findDOMNode(this);
      var ctx = el.getContext("2d");
      var chart = new Chart(ctx)[chartType](nextProps.data, nextProps.options || {});
      this.state.chart = chart;
    };
dougmolineux commented 8 years ago

I think that you're chartType variable there might be defined incorrectly.

I suggest you change it to look something like this:

        var chart = new Chart(ctx, {
          type: chartType.toLowerCase(),
          data: nextProps.data,
          options: nextProps.options
        });

EDIT / UDPATE: Sorry I took a look at the original source code I think you need to do:

return <Line data={chartData} width="600" height="250"/>

or this

return <line data={chartData} width="600" height="250"/>
SylarRuby commented 8 years ago

@dougmolineux Not sure I follow. I can't change anything as that's the npm's code.

Documentation is very poor with this module. I've installed chart.js module but not required it. If I required it, same problem. This alone should just work:

var LineChart = require("react-chartjs");

var MyComponent = React.createClass({
  render() {
   var chartData = {

  };
    return <LineChart.Line data={chartData} width="600" height="250"/>
  }
});
yaoquan commented 8 years ago

I faced a similar issue with chart.js@2.0.0. Downgraded to chart.js@^1.1.1 and the things worked according to instructions.

SylarRuby commented 8 years ago

Guess I'll use rd3 instead

dougmolineux commented 8 years ago

@SylarRuby it looks like the example usage in the Readme is:

var LineChart = require("react-chartjs").Line;

var MyComponent = React.createClass({
  render: function() {
    return <LineChart data={chartData} options={chartOptions} width="600" height="250"/>
  }
});

Sorry I'm not familiar with the "LineChart.Line" chart type in your example code there:

return <LineChart.Line data={chartData} width="600" height="250"/>

SylarRuby commented 8 years ago

@dougmolineux I know that way but it's the same issue I'm having.

MatthewHerbst commented 8 years ago

@dougmolineux suggested fix in https://github.com/jhudson8/react-chartjs/issues/114 allows the package to work again for me:

In your package.json:

"react-chartjs": "git://github.com/venari/react-chartjs.git#chartjs-v2"

SylarRuby commented 8 years ago

Actually, you don't need this module. I don't see the need. The chart.js npm or the CDN on it's own just work fine so I'm no longer using this module.

dougmolineux commented 8 years ago

Please close the issue @SylarRuby :)

MatthewHerbst commented 8 years ago

@SylarRuby doesn't this module provide animation and redraw capabilities in the React way? Technically using just Chartjs will drop you out of React, which could be undesirable

SylarRuby commented 8 years ago

@MatthewHerbst I have not used "redraw" as of yet but I am sure it works as is. All I need is to display a chart, that is it, nothing too technical. Nothing breaks in React for me. I may do a Medium post on this for you more experienced dev to compare with.

MatthewHerbst commented 8 years ago

@SylarRuby I gave this more though, and I actually am starting to agree with you. Chartjs uses the canvas. Unlike SVG, changes to the canvas does not mean DOM changes. So, there isn't really a big need to worry about affects to React since your are keeping the DOM consistent.

SylarRuby commented 8 years ago

@MatthewHerbst Yes. Wrap your var myChart({...}) inside componentDidMount() then render <canvas id="myChart" height="400" width="600"></canvas> and that's it.

MatthewHerbst commented 8 years ago

Yes, although I would recommend grabbing the element (to pass the chart) via a ref instead of directly searching for the id.

SylarRuby commented 8 years ago

@MatthewHerbst Ahhhh good one ;) Made changes and works ;)

MatthewHerbst commented 8 years ago

This is how I do it for my wrapper LineChart classes. The redraw performance is noticeably better than react-chartjs when using many data points.

componentDidMount () {
  let chartCanvas = this.refs.chart;

  let myChart = new Chart(chartCanvas, {
    type: 'line',
    data: this.props.data,
    options: {
      ...
    }
  });

  this.setState({chart: myChart});
},
componentDidUpdate () {
    let chart = this.state.chart;
    let data = this.props.data;

    data.datasets.forEach((dataset, i) => chart.data.datasets[i].data = dataset.data);

    chart.data.labels = data.labels;
    chart.update();
},
render () {
  return (
    <canvas ref={'chart'} height={'400'} width={'600'}></canvas>
  );
}

The componentDidUpdate functionality allows you to update, add, or remove any data from the dataset.

code4cake commented 7 years ago

@MatthewHerbst, hey I'm getting a Chart is not defined error even when I defined in a constructor?

export default class ChartGraph extends React.Component {
    constructor(props) {
        super(props);
        this.state = { Chart: null };
    }

    componentDidMount() {
        let chartCanvas = this.refs.chart;
        let data = this.props.data ? this.props.data : "data  not available";

        let chartInstance = new Chart(chartCanvas, { // [BUG]: Offending line // Chart is not defined
            type: 'line',
            data: {data},
            options: {
                title: {
            display: true,
            text: 'My awesome chart'
                }
            }   
        });

        this.setState({ chart: chartInstance })
    }
...etc

Can`t seem to get rid of the bug. Any help much appreciate it

MatthewHerbst commented 7 years ago

@dantesolis sounds like you just forgot to import it? import Chart from 'chart.js';

xueyongg commented 7 years ago

(intermediate value)[chartType] is not a function, im getting this same issue, im using chart.js@2.2.2 and react-chartjs@0.7.3

Any advice on this?

pwhipp commented 7 years ago

A bit worrying that @MatthewHerbst fix that does not use this package at all seems to be the go here. I couldn't get this package working but his code provided a good template for getting things working (don't need the 'forEach' iteration though, you can just assign the new datasets ).

krukid commented 7 years ago

@pwhipp AFAIK it's not cool to modify state directly, bypassing setState, so I store the chart instance in a private variable. Also, it seems like a good idea to destroy the chart on unmount.

componentDidMount() {
  //...
  this._chart = myChart;
}

componentDidUpdate() {
  const chart = this._chart;
  const data = this.props.data;
  Object.assign(chart.data, data);
  chart.update();
}

componentWillUnmount() {
  this._chart.destroy();
}
MatthewHerbst commented 7 years ago

@krukid I don't bypass setState in any part of my code.

krukid commented 7 years ago

@MatthewHerbst but you're changing state properties in componentDidUpdate: this.state.chart.data.datasets = ...

MatthewHerbst commented 7 years ago

@krukid I'm not overriding state, just getting a copy of it. That's why I save it off into it's own variable.

It's equivalent to doing:

let x = { chart: 'coolChart' };
let y = x.chart;
y = 'betterChart';

Nowhere in the above does the value of x change.

prismofeverything commented 7 years ago

Getting this error also. Consensus seems to be don't use this lib??

Okay.

sanyam1212 commented 7 years ago

i'm also facing the same error !! my script is

var portfolio_b = function(data){ $scope.labels2 = []; $scope.data2 = []; for(var i = 0 ; i < data.length ; i++){ $scope.labels2.push(data[i].name); $scope.data2.push(data[i].y); } var options = { segmentShowStroke: false, animateRotate: true, animateScale: false, percentageInnerCutout: 50, tooltipTemplate: "<%= value %>%" } var ctx = document.getElementById("doughnut2").getContext("2d"); var doughnut2 = new Chart(ctx).Doughnut($scope.data2, options); document.getElementById('js-legend').innerHTML = doughnut2.generateLegend(); }

and the html is: {

} I saw it working in a fiddle : http://jsfiddle.net/vrwjfg9z/ but for me its showing **error**: TypeError: (intermediate value).Doughnut is not a function can anybody help with this, i'm using the syntax as given on angular-chart.js site(http://jtblin.github.io/angular-chart.js/)
jgentes commented 6 years ago

easiest solution: use https://github.com/jerairrest/react-chartjs-2

freakaziod210 commented 6 years ago

@MatthewHerbst Thank you sir!! You have preserved my sanity!!