React-vis: Stateless function components cannot be given refs. Attempts to access this ref will fail

Created on 6 Jul 2018  路  17Comments  路  Source: uber/react-vis

Following errors thrown while trying to render a Line Chart from the demo here.

Image

Steps to reproduce

  • Create a new react app using CRA
  • Add react-vis to dependencies
  • Create a Component with following content
import React from 'react';

import {
  XYPlot,
  XAxis,
  YAxis,
  HorizontalGridLines,
  VerticalGridLines,
  LineSeries
} from 'react-vis';

export default class Example extends React.Component {
  render() {
    return (
      <XYPlot
        width={300}
        height={300}>
        <HorizontalGridLines />
        <VerticalGridLines />
        <XAxis title="X Axis" position="start"/>
        <YAxis title="Y Axis"/>
        <LineSeries
          className="first-series"
          data={[
            {x: 1, y: 3},
            {x: 2, y: 5},
            {x: 3, y: 15},
            {x: 4, y: 12}
          ]}/>
        <LineSeries
          className="second-series"
          data={null}/>
        <LineSeries
          className="third-series"
          curve={'curveMonotoneX'}
          style={{
            strokeDasharray: '2 2'
          }}
          data={[
            {x: 1, y: 10},
            {x: 2, y: 4},
            {x: 3, y: 2},
            {x: 4, y: 15}
          ]}
          strokeDasharray="7, 3"
          />
        <LineSeries
          className="fourth-series"
          data={[
            {x: 1, y: 7},
            {x: 2, y: 11},
            {x: 3, y: 9},
            {x: 4, y: 2}
          ]}/>
      </XYPlot>
    );
  }
}
  • Import it to App.js
import React, { Component } from 'react';
import LineChart from './LineChart';
import './App.css';

class App extends Component {
  render() {
    return (
      <LineChart />
    );
  }
}

export default App;
  • Do a yarn start and see the console.

  • package.json

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "react-scripts": "1.1.4",
    "react-vis": "^1.10.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

My guess is that the XYPlot component in function _getClonedChildComponents is adding ref to the props of the child components, while the children can easily be SFCs (In the example above the components HorizontalGridLines,VerticalGridLines,XAxis,YAxis are all SFC inside XYPlot component, hence the 4 exceptions) and in that case the exception is thrown.

Most helpful comment

@mcnuttandrew on it 馃悰 馃敤

All 17 comments

I'm having exactly the same issue on a budget/financial planning application I'm working on.

Same here. Version of "react-vis": "^1.10.1"
The code os above:

import React from 'react'
import { XYPlot, FlexibleWidthXYPlot, makeWidthFlexible, XAxis, YAxis, HorizontalGridLines, LineMarkSeries, CustomSVGSeries } from 'react-vis'

export default class Chart extends React.Component {
    className = 'Chart'
    blueColor = "#0078ff"
    lineColor = this.blueColor
    markStyle = { stroke: this.blueColor, fill: this.blueColor }
    render() {
        const { width, height } = this.props;
        let plot = (
            <FlexibleWidthXYPlot
                height={height}>
                <HorizontalGridLines />
                <LineMarkSeries
                    color={this.blueColor}
                    data={[
                        { x: 1, y: 100 },
                        { x: 2, y: 400 },
                        { x: 3, y: 300 },
                        { x: 4, y: 500 },
                        { x: 5, y: 600 },
                        { x: 6, y: 400 },
                        { x: 7, y: 500 },
                    ]} />
                <CustomSVGSeries
                    // className="custom-marking"
                    customComponent="square"
                    data={[
                        { x: 1, y: 100, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                        { x: 2, y: 400, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                        { x: 3, y: 300, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                        { x: 4, y: 500, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                        { x: 5, y: 600, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                        { x: 6, y: 400, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                        { x: 7, y: 500, size: 6, style: { stroke: this.blueColor, fill: this.blueColor } },
                    ]} />
                {/* <XAxis /> */}
                <YAxis />
            </FlexibleWidthXYPlot>
        );
        return plot;
        // return makeWidthFlexible(plot);
    }
}

Same for me. Reverting to 1.10.0 removes the errors. 00ffe619542f0af7768d7a19137cbeb7f4c30a7d appears to be the cause.

@benshope mind taking a look at this?

@mcnuttandrew on it 馃悰 馃敤

Should be fixed in 1.10.2

I've just tried in 1.10.2 and still receiving the same error with the example code.

Same for me @ericzon.

Interesting, okay, re-opening

Should 馃檹 be fixed in 1.10.3

Looks like that fixed it. Thanks @benshope and @mcnuttandrew for the work on this.

@benshope @mcnuttandrew I don't think this solves correctly the issue and I've found few problem on that:

1) If I've understood correctly from the react internals, the child object you are testing for it's stateless nature is a ReactElement object and not a Component object. Debugging your code you can see that the child is a ReactElement with few properties as stated in the link provided. If you want add refs only to non stateful components you have to check the type property on the child like:

 ...(dataProps && child.type.prototype child.type.prototype.render) ? { refs } : {}

In the current implementation you will never add any ref because you are checking for child.prototype that doesn't exist on a child and the conditions are wrong (we need to add refs only if we have dataProps and the child is a statefull component, so with prototype and render methods). (see also your series-utils isSeriesChild function that checks for series and use type https://github.com/uber/react-vis/blob/master/src/utils/series-utils.js#L31 )

2) I think there was some problem with the npm publishing, because if I use the version 1.10.2 this commit is not included: https://github.com/uber/react-vis/commit/1ab5cc76c6fef9081368a201e507e232a8dd9fc2
The version 1.10.2 seems the publication of the version 1.10.1 or something in between.

@benshope after upgrading to 1.10.3, it looks like the zoomable plot doesn't work anymore. In fact inspection shows that all mouse events are not triggering.

I tried to run the examples directly in the repo from source they work well. But when used with the compiled 1.10.3 it doesn't work anymore.

@episodeyang i think there's one more patch coming down the pipe see #874

@mcnuttandrew Thanks Andrew! down grading to 1.10.1 fixed the handler responses. Looking forward to #874.

btw congrats on UChicago :P didn't know you started last year.

Should be fixed in 1.10.4 by #874

I updated to 1.10.4 and it's all OK here 馃憤

Thank you @benshope and thank you @markov00 馃槈

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Tom-Gorup picture Tom-Gorup  路  3Comments

jckr picture jckr  路  5Comments

basilaiman picture basilaiman  路  3Comments

martoncsikos picture martoncsikos  路  4Comments

ZKruse picture ZKruse  路  4Comments