Closed
Description
Seeking feedback from @etpinard @alexcjohnson @bpostlethwaite on the best location for Plotly.react
. I can imagine a few possibilities:
- it should go in
plotly.js
and we just have to add a couple lines of code to this repo to make use of it.
- Pro: react-like functionality usable from any library
- Con: more code in plotly.js
- it goes in this repo. It computes a diff (maybe using the schema to figure out what to do about array data, with optional flag to apply immutable-like reference-change logic to simplify diff computation) and sends the result to the relevant plotly.js API methods.
- Pro/con: opposites of above
Unless I'm wrong, sounds like @alexcjohnson is/will be working on Plotly.react
. I just wanted to confirm that's what this will link up with.
Activity
bpostlethwaite commentedon Jul 31, 2017
My vote is for this repo. Once we agree on that lets get it imported into https://github.com/plotly/Plotlyjs-React-Lab
rreusser commentedon Jul 31, 2017
@bpostlethwaite Can you clarify what you mean by imported?
bpostlethwaite commentedon Jul 31, 2017
well I wrote a Plotly React component for the Lab. https://github.com/plotly/Plotlyjs-React-Lab/blob/master/src/components/PlotlyReact.js
The intention is to replace it with the finished version that will be hosted elsewhere.
bpostlethwaite commentedon Jul 31, 2017
which, if here, should be imported into the lab so we can use it within that test application.
alexcjohnson commentedon Jul 31, 2017
My initial thought was to put it into the
plotly.js
repo so it would work from anyone's home-grown plotly react component - or even not in a react environment at all, which I guess is @rreusser 's Pro above. If we put it in here, what would it take for someone to use it withplotly.js
outside react, or at least outside of our react component?@bpostlethwaite I would imagine that the lab wouldn't actually need to call
Plotly.react
directly at all itself... this component would swap it in forPlotly.newPlot
, the lab would include this component, and that would be all you'd need, right?rreusser commentedon Jul 31, 2017
We could certainly expose it separately, as in
require('plotlyjs-react/diff')
or something.rreusser commentedon Jul 31, 2017
@bpostlethwaite I assumed you meant the component would be imported. Is that correct? (As opposed to a standalone method that computes a diff and used in a react component)
bpostlethwaite commentedon Jul 31, 2017
Oh sorry for the confusion. Yes I was thinking component it makes lots of sense that it is in Plotly.js
rreusser commentedon Jul 31, 2017
Tricky parts of
Plotly.react
:chriddyp commentedon Jul 31, 2017
I'm not sure if this is where folks are discussing requirements or not, but a few more things from my (Dash's) end:
Currently, calling
newPlot
resets the zoom and legend items. Some users will want zoom and legend items to reset, other users will not (https://community.plot.ly/t/preserve-trace-visibility-in-callback/5118), and some users will want to give that choice up to the user (exposing e.g. "Lock Camera" control)rreusser commentedon Jul 31, 2017
@chriddyp Yeah, I think the goal is a method that more or less diffs the input and sends it to the correct method (
relayout
,resytyle
,update
,animate
, etc).newPlot
would be the naive fallback. That's why the general format of including the component is:(to be just a bit verbose.) The important part is that you can inject your own version (including cdn if you prefer) and if it has
Plotly.react
, your component will be smart and optimized, if not, then it'llnewPlot
everything.alexcjohnson commentedon Jul 31, 2017
That's exactly the issue - that changes to the state driven by the plot's own UI do not propagate back to the state you used to generate the plot in the first place. How do we handle this? I'm not sure it's feasible to say "these are the pieces of the state that can get modified by the UI, so ignore these in the input to
newPlot
and keep what was set on the plot" - which if I'm understanding it right is what you're thinking of with things like "lock camera" andfreeze=True
- and anyway it feels to me like it would be much more powerful if we could push those changes back into the app state, and use that to flow back through the plot viaPlotly.react
.@chriddyp in general I feel like the user's intent is already clear from their UI actions - if they zoom in, then
autorange
gets turned off for those axes and data updates will not re-autorange; but if they haven't zoomed in,autorange
will betrue
still so a data update will give new ranges. Certainly you could imagine particular scenarios where you want to override that, but as long as these state changes get pushed back up to the app level I think the default behavior is pretty good as a default.So how do we accomplish this? Maybe all the internal
Plotly.relayout/restyle/update
calls should be wrapped by something that knows whether the plot is in a react environment, and if so is able to redirect to an action that modifies the state, which eventually then trickles back to the plot viaPlotly.react
? Or perhaps the easiest is to have this component listen to all events that might accompany state modifications (I guessplotly_restyle
,plotly_relayout
, andplotly_update
) and expose a handler (onPlotChange
?) that allows the dev to connect this back into their app state? That way normally the plot would already have updated itself and when the change flows back down to the plot, it will see no diff, but if the app wanted to respond to UI-driven changes with further edits - say, you zoom in and it refines the data it's displaying - it would be able to simply make that change like any other app action.Relatedly, @rreusser points out that it's not very react-like, nor good for performant diffing, for plotly.js to be mutating
data
andlayout
. @etpinard I'd like your thoughts on this but we've had users get tripped up bygd.data
andgd.layout
mostly being mutated but sometimes being replaced, would it be too big a change for us to never mutate these, only replace them?rreusser commentedon Aug 2, 2017
@alexcjohnson good points. I think the cleanest is for the component to connect to the events and trigger a callback. It could even expose a
plotly_changed
event that emits the changed properties when you interact via the UI.With this general approach the plot wouldn't have to know it's in a react environment, right?
rreusser commentedon Oct 17, 2017
Okay, to summarize some of the conclusions from various discussions, in particular with @alexcjohnson, here's the basic design regarding react:
Plotly.plot
.plotly_react
event will be emitted. The plotly component will subscribe to this and receive a set of changes applied togd.data/layout
. It will in turn issue those changes via aonChange
callback passed to the plotly react component.Plotly.applyChanges
.data
andlayout
against its copy, sees there have been no changes, and does not re-render.data
orlayout
are passed to the component, the component will issuePlotly.react
from itscomponentDidUpdate
method, which will perform the updates.Plotly.react
.nicolaskruchten commentedon Oct 18, 2017
I think I followed this correctly, and it's likely that
react-pivottable
will avail itself of point 7 and force a replot every time the UI changes, at least for now :)9 remaining items
fixes #103
fixes #103
fixes #103
nicolaskruchten commentedon Jan 23, 2018
@swiperii if you want to create a separate issue I'd be happy to try to help you accomplish your goals within the current framework. Most likely you'll need to handle the updates and feed the layout back to the props along with the new data points.
nicolaskruchten commentedon Jan 23, 2018
To clarify the next steps... The
Plotly.react
functionality will be added to plotly.js, and progress on that can be tracked here: plotly/plotly.js#1850Once the upstream functionality is in place, this React component will be modified to take advantage of it and we can then close this current issue :)
swiperii commentedon Jan 24, 2018
@nicolaskruchten Thanks for your response. I have currently made my own Plotly.react method that uses add/deleteTraces, restyle and some ugly hacks to make data updates work together with zoom and selections. There are still some bugs though, so I eagerly look forward to the real thing :)
nicolaskruchten commentedon Feb 12, 2018
Good news! The
Plotly.react
method is implemented in plotly.js version 1.34.0 and this React wrapper already takes advantage of it, so just upgrade plotly.js and things should be more reactive!AyoCodess commentedon Nov 22, 2021
is there a solution for this?. As the plot automatically re-draws when any the data object changes. i.e an x-axis data point.
bpostlethwaite commentedon Nov 23, 2021
There is a Plotly react component that was produced from this here: https://github.com/plotly/react-plotly.js/
There is also the .react method on the vanilla plotly object.