codesuki / react-d3-components

D3 Components for React
http://codesuki.github.io/react-d3-components/example.html
MIT License
1.63k stars 206 forks source link

DefaultScalesMixin cannot read property '0' of undefined. #87

Closed PAK90 closed 8 years ago

PAK90 commented 8 years ago

I'm attempting to use this charting library for my dataset of about 15,000 points; I want a simple scatter graph. My data is in the format:

...
{
      "label": "label1",
      "x": -2.84194509027,
      "y": -0.758540839391,
      "r": 0.0,
      "g": 1.0,
      "b": 0.0,
      "cmc": 4
    },
    {
      "label": "label2",
      "x": 1.54194586524,
      "y": 0.253299257011,
      "r": 0.588235294118,
      "g": 0.294117647059,
      "b": 0.0,
      "cmc": 1
    }, ...

where x and y are the [x,y] coords, rgb are colour components, and label is what I want on the tooltip. My code is pretty damn simple:

import React from 'react';
import ReactDOM from 'react-dom';
var R3D = require('react-d3-components');
var ScatterPlot = R3D.ScatterPlot;

var margin = {top: 10, bottom: 50, left: 50, right: 10};
var data = require('./data/data.json');

var CosinePlot = React.createClass({
    render: function() {
        return <ScatterPlot 
            data={data}
            width={400}
            height={400}
            margin={margin}/>;
    }
});

export default CosinePlot;

However, when I attempt to load this on my page I get an error on line 72 of DefaultScalesMixin.js; "Uncaught TypeError: Cannot read property '0' of undefined". Is there a way to specify to the ScatterPlot that I want the x and y values to be the [x,y] coordinates?

codesuki commented 8 years ago

Going from this sample:

data = [{
    customLabel: 'somethingA',
    customValues: [[0, 3], [1.3, -4], [3, 7], [-3.5, 8], [4, 7], [4.5, 7],  [5, -7.8]]
}];

var labelAccessor = function(stack) { return stack.customLabel; };
var valuesAccessor = function(stack) { return stack.customValues; };
var xAccessor = function(element) { return element[0]; };
var yAccessor = function(element) { return element[1]; };

React.render(<ScatterPlot
                data={data}
                width={400}
                height={400}
                margin={{top: 10, bottom: 50, left: 50, right: 10}}

                label={labelAccessor}
                x={xAccessor}
                y={yAccessor}
                values={valuesAccessor}/>,
            document.getElementById('location'));

Each stack is 1 element of the data array. It has customLabel and customValues fields. In your case since the layout is flat... maybe try

var valuesAccessor = function(stack) { return stack; }; // since it's not a field but the object itself

and

var xAccessor = function(element) { return element.x; };
var yAccessor = function(element) { return element.y; };

Didn't have time to test it but maybe it gives you an idea.

PAK90 commented 8 years ago

OK, so now my code is:

var ScatterPlot = R3D.ScatterPlot;

var margin = {top: 10, bottom: 50, left: 50, right: 10};
var valuesAccessor = function(stack) { return stack; };
var xAccessor = function(element) { return element.x; };
var yAccessor = function(element) { return element.y; };

var CosinePlot = React.createClass({
    render: function() {
        return <ScatterPlot 
            data={cardData}
            width={400}
            height={400}
            margin={margin}
            x={xAccessor}
            y={yAccessor}
            values={valuesAccessor}/>;
    }
});

export default CosinePlot;

I put a breakpoint in the valuesAccessor return, and on page load it seems to work; it shows me one data point with all 7 attributes. However, it fails on the xAccessor, saying that 'element' is undefined and therefore unable to find x. How does one define 'element' for those two functions?

PAK90 commented 8 years ago

Solved the problem with changing the valueAccessor to return stack.cards, since my data was wrapped in a "cards": [ {data},{data} ] format.

However, now I have a second issue; I have a lot of data points. It's rendering just under 15,000 points, and this is making the rest of my page a bit slow (clicks and animations take longer to proceed, etc.). Is there any way I can make it faster?

codesuki commented 8 years ago

I am glad to hear you figured out the accessors. About the performance question... I have to think about it. Not so easy to answer. Do you know exactly when it slows down? Redraw?

PAK90 commented 8 years ago

It's slow at all points. Just having the 15,000 points on the page is making all other elements animate/respond slowly.