Black Lives Matter. Please consider donating to Black Girls Code today.

Pattern for avoiding circular dependency in Dash callbacks

I’m having trouble converting a fairly simple React concept into Dash – I need to set the state before AND after a long running task. I have a dashboard where a button initiates “long running task”, the completion of which populates the dashboard. I would like to display a loading message in the meantime. In React I would set an isLoading property and update the state accordingly upon completion of “long running task”. In dash, I am attempting to replicate this with a hidden “status” div that toggles between “ready/loading”. The flow I would like is:

  • User clicks button to start process

  • Status div changes to “loading”

  • The loading screen is listening to the Status div and updates to be visible

  • The long running process begins

  • After the process finishes, the status div is updated to ready

  • Loading animation becomes invisible

  • Resulting dashboard becomes visible

My callback structure:

  • Status div listens to button click (sets status to “loading”) and graph data to set to know when completed (set “ready”)
  • graph data listens to status div to know when to begin the calculation
  • loading screen listens to status div to know when to display and to graph data to know when to stop

However, this causes a circular dependency error because button -> status -> graph -> status -> graph

Is there a different pattern that can accomplish this in Dash?

As a quick workaround, your global dash app container get the CSS class ._dash-loading-callback when updating its content. You might have look at 📣 Dash Loading States to see if you could use this.

Otherwise, if I understand your app correctly, I would create following callbacks:

  1. Set_loading_status:
  • Input: button, n_clicks
  • Output: status_div, children
  1. Start_long_process:
  • Input: button, n_clicks
  • Output: graph, figure
  1. Update_loading_status:
  • Input: graph, figure
  • Output: status_div, children

This way, 1 and 2 are fired together, and 3 is fired when 2 is completed. You would put both “loading” and the animation in status_div (hard to be more explicit without some proper MWE).
(This might be a bit more difficult as 1 and 3 have the same output — and I think I remember you cannot have two callbacks with the same output (for the moment). If it’s actually the case, you should create one global callback with both 1 & 3 triggers, retrieve which trigger fired the callback, and set output accordingly.)

You can show/hide the graph using CSS (display: none or visibility: hidden, depending on what you want to achieve). You would then need a 1bis and 3bis callbacks that have the same inputs, and use graph, style (or — preferably — graph, className if you use proper CSS).

You pretty much have described what I have currently implemented. As you mentioned, 1 + 3 have to be combined. An issue I have found with having 1 and 2 is that I am unable (I think) to control the order that the callbacks fire, so what I encounter is that once the start button is clicked the loading screen does not appear until after the long running process has completed. This can equivalently be seen by changing the style of some other element onclick with the same button that triggers the long running task.

I get it now. IMHO, what you are looking for is: “how to define the fire order for callbacks having the same trigger” (I assumed they would have been fired simultaneously).

I’ve looked a bit around and it seems that if two callbacks are to be triggered “simultaneously”, there is no way to define which will actually be fired first. (Note that more experienced user might have more insights on this.)
To get a clearer view of the callback, you can have a look at Dash callback chain (kudos to @OliverBrace). Yet this doesn’t solve your issue.

Note: this is a WIP: I just realize we’re facing the same issue (two callbacks fired at the same time)

Here is a logic way that could work:

You have to create a hidden placeholder_div. When you click on the button, you will update the content of this placeholder_div. You make sure you actually change it by reading its content using a State

1 Like

This is not working for me. see Multiple Callbacks for single inputs - not all are firing

1 Like