-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
callback triggered while dash.callback_contract.triggered is [{'prop_id': '.', 'value': None}] #1523
Comments
To circumvent the issue, I could use the following decorator def avoid_untriggered_call(f):
"""Decorator that cancel any call to the callback if the trigger is [{"prop_id": ".", "value": None}]."""
@wraps(f)
def helper(*args, **kwargs):
if dash.callback_context.triggered == [{"prop_id": ".", "value": None}]:
return dash.no_update
return f(*args, **kwargs)
return helper on each of the callback but then I would miss the initial calls to the callback at the start of the app (AFAIK) |
Thanks @sdementen - possibly related to #1519 The While we're here I'll point out that instead of dash/dash/_callback_context.py Lines 21 to 31 in 3402cb8
|
Oh actually, I didn't fully understand what you were doing at first. You've found the loophole that effectively you can create a circular callback chain by having the output of a callback be its parent's I'm not clear on why you need this to function like multiple callbacks all outputting to the same prop, as opposed to having all of those same inputs feeding into one callback, or at least having a separate callback combining them all into one final output. What about a clientside merge callback, like @nicolaskruchten describes in plotly/dash-core-components#881 (comment) ? |
tx @alexcjohnson for your insight! On my initial problem, I am indeed changing the parent container children so that it resets the writer stores. Hence, at any time, only the root store has content (as the writer stores have been reset) except when a callback is triggered by one of the writer stores. The writer stores are only used as
Regarding the client side callback, this is indeed an excellent idea/suggestion. It removes all "spurious" callbacks and make the whole more reactive. I will make a post on the plotly community when the details are ironed out |
Ah yes, that part of the advanced callbacks doc page is not quite correct. If the new components added to the layout contain callback outputs, these callbacks also need to fire. This is similar to what happens on page load: we don't assume the component was created with the prop values it ultimately should have, we allow the callback to run and decide that. There is some subtle logic in this case surrounding what props count as having triggered the callback - the key distinction being whether the entire callback (inputs and outputs at least, I'd have to look back to see where we landed on state) is contained within the new layout fragment. If so, it's treated EXACTLY like the initial page load with respect to cc @jdamiba - I missed this point when we were discussing these details, perhaps we can elaborate on this section? Most important is the point about newly-created outputs triggering callbacks, but we should sort out the details re: |
@alexcjohnson I agree that it would be a good idea to update the section that covers this behavior in dash-docs. Send me an invite for a meeting so we can get on the same page :) |
@jdamiba @alexcjohnson it would be nice, besides the update of this section of the doc, to have a documentation on the interactions between frontend/client and server with the logic around the callback graph, the format of the JSON send from the client to the server and vice-versa. |
Logic around the callback graph definitely, we should document fully how and when each callback is triggered in many different cases. @jdamiba has added all sorts of great info about this in https://dash.plotly.com/advanced-callbacks, "When Are Callbacks Executed?" as well as https://dash.plotly.com/app-lifecycle and he and I will take another pass through this at some point, but if there's still missing or incorrect info there please let us know (or make a PR 🏆 ) And I suppose given that we have multiple back ends, the client-server contract is relatively firm. It's not real high on our priority list but we'd happily include this in the docs if anyone is motivated to write it! |
I would be interested in the documentation of the graph of dependencies on the client side and on the logic that trigger the callbacks in function of the graph events. |
Describe your context
I am trying to use a Store that could be written by multiple callbacks (to circumvent the 1 output can only be updated by one callback). The logic (hack?) looks sound and works except that I get a problem with a callback that is triggered with
dash.callback_contract.triggered == [{'prop_id': '.', 'value': None}]
each time an unrelated Div is updated (ie not only on the first firing at the beginning of the app) and is moreover triggered twice.Here is the sample app with the
get_multi_store
function generating a Div with multiple stores (one core and one per writer).pip list | grep dash
belowif frontend related, tell us your Browser, Version and OS
Describe the bug
After the initialization of the app, the Store "scenario" holds the value:
[{'a': '0'}, {'b': '0'}, {'c': 0}]
When increasing the Input "a", the store changes to (as the input 'a' and the input 'c' are successively changed)
[{'a': '0'}, {'b': '0'}, {'c': 0}, {'a': 1}, {'c': 0.5}]
However, I see that the callback
set_a_and_c
is triggered once when the input 'a' is changed (OK) and twice afterwards with the lineprint(dash.callback_context.triggered)
printing[{'prop_id': '.', 'value': None}]
Expected behavior
I would expect the callback
set_a_and_c
to be only triggered once withdash.callback_context.triggered==[{'prop_id': 'a.value', 'value': 1}]
.Moreover, if I change the input 'c', I also see that the callback
set_a_and_c
is called twice with thedash.callback_context.triggered==[{'prop_id': 'a.value', 'value': 1}]
.If I update the input 'b', then the callback
set_a_and_c
is called once with thedash.callback_context.triggered==[{'prop_id': 'a.value', 'value': 1}]
.The text was updated successfully, but these errors were encountered: