dash
dash copied to clipboard
Support for callbacks with no outputs
This PR allows callbacks to have no return values. This is the most requested feature on this repo.. Personally, I can see multiple examples where this feature can be used. It can be used to, let's say, make a post request to a website we don't need the response for, for eg. tracking clicks. Other examples, for eg, opening a new website (using clientside callbacks) and many applications.
Here's a basic example of how this might work.
from dash import Dash, html, callback, Output, Input
app = Dash(__name__)
app.layout = html.Div([
html.H1(children='Title of Dash App', style={'textAlign':'center'}),
html.Div(id="result"),
html.Button(id='output-button',children="This button gives an output"),
html.Button(id='no-output-button',children="no output button"),
])
@callback(
Output("result","children"),
Input("output-button","n_clicks")
)
def make_result(n_clicks):
return f"Button with output looks like this {n_clicks}"
@callback(
Input("no-output-button","n_clicks"),
force_no_output=True
)
def make_result(n_clicks):
print("Ignored",n_clicks)
return None
if __name__ == '__main__':
app.run(debug=True)
This new feature is built on the existing logic used for duplicate outputs. I've added conditions to the error statements that overwrite the behaviors specifically for no-output callbacks. I imagine the final version will have warnings on the terminal and more rigid statements. However, this implementation is convincing to me to be in the production env. What do you folks think? What other changes should we make?
Contributor Checklist
- [X] I have broken down my PR scope into the following TODO tasks
- [X] Basic MVP Working
- [ ] A generalize function wrappers(?) => 0 outputs automatically forces the attribute.
- [ ] More Tests needs (also rewrite old tests)
- [X] I have run the tests locally and they passed. (refer to testing section in contributing)
- [ ] I have added tests, or extended existing tests, to cover any new features or bugs fixed in this PR
Thanks @yashjha123, looks like a very promising start! Three things before we dig too deeply into this:
- Would you mind rebasing or recreating this PR off the
dev
branch instead ofmaster
, and ensuring none of the build artifacts (dash/dash-renderer/build/*
) are committed? - As mentioned in https://github.com/plotly/dash/issues/1549#issuecomment-1668401201 from @T4rk1n we should be able to do this without users needing to set a flag in the callback definition, just by looking at how many outputs the callback defines. If you want to generate that flag behind the scenes and pass it to the renderer that's fine, but we shouldn't make users do that.
- Tests will be very important here, and we'll need them to cover quite a lot of situations: direct initial call, indirect initial call (ie the input is the output of another initial callback), direct user input, indirect user input, pattern matching with
MATCH
input, pattern matching withALL
input... we can start reviewing prior to tests but we'll need them before we can merge. Because these callbacks are only expected to have server-side effects, the best pattern to use is probablymultiprocessing.Value
as for example in cbmt001 - but this feature deserves a new test file in the same folder.
Thank you for opening this PR, I adapted part of the code found here to not require setting a flag and allow for multiples no output callbacks.
Closing as implemented in #2822