canvasXpress
canvasXpress copied to clipboard
graphType Network crashed when user shift rendered pictute with LMB
Initially graph rendered ok. Crash is occured after user holding left mouse button and moving it (to shift rendered picture in viewport)
javascript callstack on crash:
you can see that node.layout.displaycement field is undefined.
to reproduce you can use python script and json data which python script used
data network.json
from canvasxpress.canvas import CanvasXpress
import json
import math
from dash import Dash, html
from canvasxpress.render.dash import CXElementFactory
with open("network.json", "r") as f:
data = json.loads(f.read())
cx = CanvasXpress(
render_to = "test",
data = data,
config = {
"background": "rgb(100,255,255)",
"calculateLayout": True,
"networkLayoutType": "forceDirected",
"graphType": "Network",
},
width = 1400,
# height = 800
)
g_app = Dash(__name__)
g_app.layout = html.Div(
id="cx-container",
style={"textAlign": "center"},
children=CXElementFactory.render(cx),
)
if __name__ == "__main__":
g_app.run_server(debug=True)
I can't reproduce . I am asking a collaborator to check. Sorry for the delay.
@docinfosci can you check - script is in python
Thanks! I am confirming that I've seen this and will investigate.
@glempi -- try setting render_to = ""
(empty string). This forces CanvasXpress for Python to generate anonymous IDs when passing generated configurations or JavaScript to the Web browser for use by CanvasXpress for JavaScript.
Why?
Dash uses React for its JavaScript, and React requires that UI updates destroy and recreate UI JavaScript objects when updates occur instead of reusing existing objects. But, in this case, an HTML canvas element is also generated using whatever ID is provided. CanvasXpress for JavaScript pays attention to the canvas element ID. There's a moment of opportunity in which CanvasXpress for JavaScript thinks there is still a chart object named the same ID as the canvas element when in fact the DOM/React has disposed of the old object and a new one has yet to be created to take its place—in which case running code can crash. By using anonymous IDs a new ID is assigned to the canvas element with each refresh, so when CanvasXpress for JavaScript attempts to deal with the associated object there is one available and thus avoids the crash. Non-React environments don't have this issue, so in many cases, such as Jupyter Notebooks, using an assigned ID for each chart makes a lot of sense.
Cheers, @docinfosci
Funny about the React philosophy. Why would you want to reuse/fix an existing/old object if I can buy a brand new one. (Pretty much the American mentality :-) :-) :-)
So true! It's maddening. I've been considering whether chart rendering for a Dash context should force anonymity, or whether a warning should be printed in the logs. For now, education seems the better approach as it avoids other issues like, for example, people not understanding why custom JavaScript can't find their object by ID.
Thanks! I am confirming that I've seen this and will investigate.
@glempi -- try setting
render_to = ""
(empty string). This forces CanvasXpress for Python to generate anonymous IDs when passing generated configurations or JavaScript to the Web browser for use by CanvasXpress for JavaScript.Why?
Dash uses React for its JavaScript, and React requires that UI updates destroy and recreate UI JavaScript objects when updates occur instead of reusing existing objects. But, in this case, an HTML canvas element is also generated using whatever ID is provided. CanvasXpress for JavaScript pays attention to the canvas element ID. There's a moment of opportunity in which CanvasXpress for JavaScript thinks there is still a chart object named the same ID as the canvas element when in fact the DOM/React has disposed of the old object and a new one has yet to be created to take its place—in which case running code can crash. By using anonymous IDs a new ID is assigned to the canvas element with each refresh, so when CanvasXpress for JavaScript attempts to deal with the associated object there is one available and thus avoids the crash. Non-React environments don't have this issue, so in many cases, such as Jupyter Notebooks, using an assigned ID for each chart makes a lot of sense.
Cheers, @docinfosci
Unfortunately render_to="" doesn't help layout.displacement property still undefined after shifting viewport
Is this completed?