Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plotly selection state is lost when re-rendering. #147

Open
DylanVann opened this issue May 31, 2019 · 17 comments
Open

Plotly selection state is lost when re-rendering. #147

DylanVann opened this issue May 31, 2019 · 17 comments

Comments

@DylanVann
Copy link

DylanVann commented May 31, 2019

This codepen shows the issue: https://codepen.io/dylanvann/pen/OYaedz

The onHover handler forces a re-render.

Whenever the Plot is re-rendered some state is lost. In particular the selection is lost.

How it behaves when re-rendering (selection box is not maintained):

selection

How it behaves when not re-rendering (selection box is maintained):

better-selection

@DylanVann DylanVann changed the title Plotly state is lost when re-rendering. Plotly selection state is lost when re-rendering. May 31, 2019
@nicolaskruchten
Copy link
Contributor

You should be able to use uirevision to avoid most such problems: https://plot.ly/javascript/uirevision/

@DylanVann
Copy link
Author

It does not seem to work for selection state.

@nicolaskruchten
Copy link
Contributor

In your codepen, what does the problem look like? Can you post a gif? I can't replicate any issues on this end...

@DylanVann
Copy link
Author

Posted a couple gifs in the description.

@nicolaskruchten
Copy link
Contributor

Oh I see, the selection box disappears. Yes, this is not something which is persistent in plotly.js at the moment (it's not part of the figure spec at all actually) ... issue: plotly/plotly.js#1851

@DylanVann
Copy link
Author

Cool. Ideally to fit React's model selection could even be a controlled prop.

@nicolaskruchten
Copy link
Contributor

Yes, this would be ideal but the underlying Plotly.js library doesn't really work in such a way as to be compatible with this. The idea behind uirevision is for it to be more controllably uncontrolled :)

@yifei-zhan
Copy link

@DylanVann you can control the constraint-range + range + selectedpoints property of traces to maintain the select state yourself, but it takes a lot of time. The api is not programmer-friendly

@will-moore
Copy link

Just ran into this issue myself.
When I drag to select a region on the scatter plot, I want to show the selected items so I'm using onSelected to update the selected IDs in a parent Component. But unfortunately this state change is causing the <Plot/> inside the <PlotContainer /> to re-render and so I don't see the selection change in the Plot:

Component = () => {
    const [selectedIds, setSelectdIds] = React.useState([]);

    return (
        <div>
            <PlotContainer setSelectdIds={setSelectdIds} />
            <ShowSelected selectedIds={selectedIds} />
        </div>
    )

Any pointers or workarounds would be much appreciated? Thanks.

@will-moore
Copy link

Actually, I re-read the issue above and realise that was really concerned about the selection box but I'm not too bothered about the box. For me, I lose the selection itself. Is there a way to preserve the selected points? I've used all the state management described at https://github.com/plotly/react-plotly.js#state-management to preserve the axis ranges etc but I don't see selected objects in any of that state?

@matthias-ccri
Copy link

It would be good to get the selection as an input props. I was hoping to use react-plotly. I'm implementing something like crossfilter where the plot selections/brushes are a key part of the interface.

However it sounds like the underlying plotly library doesn't have robust selection support. Is there some workaround, so I can use react-plotly instead of d3? — maybe overlaying my own selection box outside of plotly, but then it would have to synchronize with the margins and scales.

@will-moore
Copy link

I'm using Plotly with crossfilter, and it seems that sometimes I am losing the current selection because of a re-render and sometimes not. Haven't got to the bottom of it yet....
https://github.com/will-moore/parade-crossfilter/blob/master/src/plots/Plot.js is my wrapper to maintain axis ranges on re-render. The parent https://github.com/will-moore/parade-crossfilter/blob/master/src/plots/ScatterPlot.js listens for when the crossfilter filter changes to update the plot. Based on React-crossfilter example at https://www.lighttag.io/blog/react-dc-js/.

@m-podlesny
Copy link

@DylanVann Is your problem resolved? Shall we close this issue?

@DylanVann
Copy link
Author

As far as I'm aware it is not.

@mlisthenewcool
Copy link

Any update on this issue ?

@juls-k
Copy link

juls-k commented Nov 10, 2021

I have same issue, In React when it's re-rendering.

@sellings-dev
Copy link

sellings-dev commented Jun 18, 2023

I see this is an old issue, but I've been recently successful in working around it by using the selections attribute from the plot's layout object. The idea was to use it as a controlled prop as discussed earlier.

Essentially, I have the onSelected callback set a state on the parent component. The state is set to be event.selections. I then pass this same state as a prop for the plot component and make it the value of the selections attribute. To clear the selection, I just set the state to an empty array. Something like this:

// Parent Component

function ParentComponent(){
  const [selections, setSelections] = React.useState([])

  const handleSelect = ( event ) => {
    setSelections( event.selections )
  }

  const handleDeselect = ( event ) => {
    setSelections([])
  }

  return (
    <ChildComponent selections={selections} handleSelect={handleSelect} handleDeselect={handleDeselect} />
  )
}


// Child Component

function ChildComponent({selections, handleSelect, handleDeselect}){
  return (
    < Plot
      data={...}
      layout={{
        ...,
        selections: selections,
        ...
      }}
     onSelected={handleSelect}
     onDeselect={handleDeselect}
    />
  )
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants