emilhe / dash-extensions

The dash-extensions package is a collection of utility functions, syntax extensions, and Dash components that aim to improve the Dash development experience
https://www.dash-extensions.com/
MIT License
415 stars 59 forks source link

Javascript errors on Mermaid flow chart creation #155

Open jp273 opened 2 years ago

jp273 commented 2 years ago

Firstly this module is great and I am using both the FileSystemCache and Mermaid in the dash app I am developing. I'm using the mermaid tool to create a flow chart from my dash app. In a simple dash test app (just creating and showing the flow chart) I am seeing javascript errors 10-20% of the time on page reload. Does anyone have an idea what is going on? Is there something else I should be doing? For my test app I have a simple callback like this:

@app.callback(Output('scenario-img', 'children'), Input('test-interval', 'n_intervals')) def update_scenario_img(n_intervals): mermaid_chart = Mermaid(chart=chart) return mermaid_chart

The error is below. Sorry I don't know enough about javascript or react to know where to start! Happy to try more things or provide more information if it helps.

(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)

Error: Failed to execute 'querySelector' on 'Document': '#9Qcg6 g' is not a valid selector.

at ou (http://127.0.0.1:8050/_dash-component-suites/dash_extensions/async-mermaid.js:1:285064)

at http://127.0.0.1:8050/_dash-component-suites/dash_extensions/async-mermaid.js:1:620935

at Object.render (http://127.0.0.1:8050/_dash-component-suites/dash_extensions/async-mermaid.js:1:622380)

at v (http://127.0.0.1:8050/_dash-component-suites/dash_extensions/async-mermaid.js:1:1101152)

at renderWithHooks (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_3_1m1649950914.14.0.js:14938:20)

at updateFunctionComponent (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_3_1m1649950914.14.0.js:17169:22)

at mountLazyComponent (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_3_1m1649950914.14.0.js:17483:19)

at beginWork (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_3_1m1649950914.14.0.js:18737:18)

at HTMLUnknownElement.callCallback (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_3_1m1649950914.14.0.js:182:16)

at Object.invokeGuardedCallbackDev (http://127.0.0.1:8050/_dash-component-suites/dash/deps/react-dom@16.v2_3_1m1649950914.14.0.js:231:18)
kaburelabs commented 2 years ago

Found this same problem trying to run the example snippet dash-extensions docs

The error I found is almost the same one you got: Failed to execute 'querySelector' on 'Element': '#169mA g' is not a valid selector.

disanman commented 1 year ago

I am also getting that error, but it's not always happening. When it happens, the flow chart is not displayed. Then if I refresh the dash app, it seems to work again. Here I post the full error:

(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser's console.)
Error: Failed to execute 'querySelector' on 'Element': '#8qLew g' is not a valid selector.

    at HTMLBodyElement.<anonymous> (http://localhost:5000/_dash-component-suites/dash_extensions/async-mermaid.js:1:279826)

    at ru.select (http://localhost:5000/_dash-component-suites/dash_extensions/async-mermaid.js:1:290466)

    at http://localhost:5000/_dash-component-suites/dash_extensions/async-mermaid.js:1:650047

    at Object.render (http://localhost:5000/_dash-component-suites/dash_extensions/async-mermaid.js:1:651552)

    at v (http://localhost:5000/_dash-component-suites/dash_extensions/async-mermaid.js:1:1132540)

    at renderWithHooks (http://localhost:5000/_dash-component-suites/dash/deps/react-dom@16.v2_4_1m1664958241.14.0.js:14938:20)

    at updateFunctionComponent (http://localhost:5000/_dash-component-suites/dash/deps/react-dom@16.v2_4_1m1664958241.14.0.js:17169:22)

    at beginWork (http://localhost:5000/_dash-component-suites/dash/deps/react-dom@16.v2_4_1m1664958241.14.0.js:18745:18)

    at HTMLUnknownElement.callCallback (http://localhost:5000/_dash-component-suites/dash/deps/react-dom@16.v2_4_1m1664958241.14.0.js:182:16)

    at Object.invokeGuardedCallbackDev (http://localhost:5000/_dash-component-suites/dash/deps/react-dom@16.v2_4_1m1664958241.14.0.js:231:18)
strangemonad commented 1 year ago

This is due to the nature of the async variant of mermaid.js. There seems to be a concurrency bug in mermaid async between react mounting the Mermaid component and the mermaid.js api rendering the svg for a graph. Lending credence to this, when I try to mount a Mermaid component with a larger definition, it seems to trigger more often.

The solution I found was to make sure the Mermaid component is mounted before trying to set it's chart props (init values seem fine.

e.g.

bp.layout = 
      ...
      Mermaid(id="my-chart", [config=...])
     ...

@bp.callback(
    Output("my-chart", "chart"),
    Input("my-chart", "id"),
def on_mermaid_created(id: str) -> str:
     return """
         flowchart TD;
           ...
     """

alternatively, you can make Input("my-chart", "id") a Trigger if you have that transform installed since we're just using it for the purpose of getting called back after the react component is initialized and the component has been mounted in the dom.

at least, I've not seen the issue again after I started doing things that way. In practice, I don't see that as a huge inconvenience since I often want to render graphs that are based on other state as part of a callback anyway, you just need to not have that callback return a Mermaid but rather a str that's set to the chart prop of an existing Mermaid