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

Best way to check if a callback input has changed its value?

I want to do some optimizations in my callbacks depending on what dash Inputs has changed from the previous call.
React components store their previous state and props along with the new ones, making it easy to accomplish this.
What’s the best way to do it in Dash callbacks?

I discover a nice (maybe too obvious?) way to do this. I share it here in case someone find it helpful as well.
You cannot have the same Component for both Input and Output, but you can have the same component both in Input and State. So, if you need to know the previous state of the component and act accordingly, you can just have it as input as an State component.
For example, if you need to know if the component foo has changed, you could do:

 @app.callback(Output('result', 'children'),
        [Input('foo', value')],
        [State('foo', 'value')]
        )
    def has_changed_foo(input, previous_state):
      if (previous_state == input):
        raise PreventUpdate('No changes...')
      else:
        return 'has changed'

Disclaimer: Not tested, but should work.

This doesn’t actually work. State will be the same value as Input, rather than the previous value.

Right now, the only way to tell which input has fired is to use an html element and the n_clicks_timestamp property.

We’ll solve this in the future but it’s a big project. We’re looking at sometime next year unless a company steps up to sponsor it (https://plot.ly/products/consulting-and-oem/).

Oh, my mistake :frowning: What I’m actually doing is to use the same component for both State and Output, so when I get some Input, I check “the current state” with State and decide if I have to update the Output .
So, hopefully, this should work:
@app.callback(Output(‘foo’, ‘children’),
[Input(‘trigger’, value’)],
[State(‘foo’, children’)]
)
def has_changed_foo(input, previous_state):
if (previous_state == ‘initial’):
return ‘Content’
else:
raise PreventUpdate(‘foo already created once, no need to created any more…’)

I’m using this, for instance, to generate a html element once and only once, when some input is given.

1 Like