Open
Description
Description
After running a callback with Output
and State
on the graph JSON, the update cycle is broken.
This affects Scale AI and Hydro Quebec.
CC: @mtwichan @alexcjohnson @mj3cheun @jackparmer
Steps/Code to Reproduce
This is a minimal example adapted from another reproducible example from Matthew (@mtwichan). You can drag around the nodes in the demo to easily demonstrate the issue:
- Press the print-JSON button.
- Move a node around.
- Press the JSON button again.
- Note that the position changed, reflecting the drag.
- Press the break button, which has input/output arguments on the JSON.
- Move the node around again.
- Press the JSON button. The position is not updated this time, or any time after this.
Notes:
- This is very likely to affect other JSON as well (e.g.
data
), though position is simple and clear to demonstrate. - This may need to be filed in Dash rather than here, as this may be a general issue with Dash.
- You can drop this file into this repo in the root as something like
usage.py
to quickly verify.
import dash
import dash_cytoscape as cyto
import dash_html_components as html
from dash.dependencies import Input, Output, State
import json
from dash.exceptions import PreventUpdate
from copy import deepcopy
app = dash.Dash(__name__)
server = app.server
app.layout = html.Div([
cyto.Cytoscape(
id='cytoscape',
elements=[
{'data': {'id': 'one', 'label': 'Node 1'},
'position': {'x': 50, 'y': 50}},
{'data': {'id': 'two', 'label': 'Node 2'},
'position': {'x': 200, 'y': 200}},
{'data': {'source': 'one', 'target': 'two', 'label': '1 to 2'}}
],
layout={'name': 'preset'}
),
html.Button("Print elements JSONified", id="button-cytoscape"),
html.Button("Break", id="button-break"),
html.Div(id="html-cytoscape"),
])
@app.callback(
Output("html-cytoscape", "children"),
[Input("button-cytoscape", "n_clicks")],
[State("cytoscape", "elements")],
)
def testCytoscape(n_clicks, elements):
if n_clicks:
return json.dumps(elements)
@app.callback(
Output("cytoscape", "elements"),
[Input("button-break", "n_clicks")],
[State("cytoscape", "elements")],
)
def breakCytoscape(n_clicks, elements):
if n_clicks:
return deepcopy(elements) # happens with a deep copy or not
else:
raise PreventUpdate
if __name__ == '__main__':
app.run_server(debug=True)
Expected Results
The update cycle should continue.
Actual Results
The update cycle is stopped.
Versions
@mtwichan, would you post your versions here for reference?
Metadata
Metadata
Assignees
Labels
No labels