plotly / react-pivottable

React-based drag'n'drop pivot table with Plotly.js charts
https://react-pivottable.js.org/
MIT License
996 stars 254 forks source link

Updating PivotTableUI prop does not always force a re-render of child renderer #43

Open drheinheimer opened 6 years ago

drheinheimer commented 6 years ago

I'm trying to create what amounts to my own version of Plotly's react-chart-editor. In doing so, I'm passing a layout prop to my component, which I then include in my PlotlyRenderer.js for the final render. Pretty straightforward. However, updates to layout (changes in chart title, etc.) propagate only to the first PivotTableUI configuration. If I change the configuration (pivot the data), subsequent changes to layout do not propagate to the child plot renderer.

My solution to this is to add a key to the main PivotTableUI component, consisting of the stringified version of the layout object. I.e., <PivotTableUI key={JSON.stringify(layout)} ...otherProps />. This works, but I'm not sure if it's correct. If it is correct, perhaps this should be done within the PivotTableUI component itself? An alternative might be to use componentWillReceiveProps and shouldComponentUpdate?

nicolaskruchten commented 6 years ago

I'm not sure I'm following exactly what you're trying to do... are you able to provide a minimal example piece of code I can play with? One thing I wonder is if you are making immutable changes to layout, i.e. is the identity of the layout object changing when you change one of its keys? If not, then I wouldn't expect the plot to refresh, as this is what will trigger it because it is a React.PureComponent.

drheinheimer commented 6 years ago

It sounds like you understand what's going on, even though I don't. What do you mean by "is the identity of the layout object changing when you change one of its keys?" I'm guessing this is related to https://github.com/plotly/plotly.js/issues/2389, and, hence, the react-plotly basic props warning but not sure.

Still, here's a simplified version of my code, with some bits excluded (such as data, actual layout content, etc.). The PivotTableUI component:

<PivotTableUI
    key={JSON.stringify(layout)}
    data={data}
    onChange={this.onChangePivot}
    renderers={{...TableRenderers, ...PlotlyRenderers}}
    {...this.state.pivotProps}
    layout={layout}
    aggregators={aggregators}
/>

where layout is some JSON object to be passed to the Plotly chart (axis configuration, etc.). Within the Plotly renderer, I've added the following:

if (this.props.layout) {
    layout = {...layout, ...this.props.layout};
}

and:

return (
    <PlotlyComponent
        fit={true}
        data={data}
        layout={layout}
        config={PLOTLY_CONFIG}
    />
);

The issue is that after the data is pivotted (i.e., by updating state.pivotProps in this.onChangePivot), the PlotlyComponent no longer responds to layout changes. Unless I change the key. It could be that changing the key is the right way to do this (i.e., start from scratch), but not sure. It's also possible (likely?) this is a Plotly issue rather than a PivotTableUI issue.

Fyi, here's a screenshot of my goal (again: something like Plotly's own plot designer, but much simpler):

image