Description
Description:
I'm experiencing an issue with the dcc.Upload component in Dash. When I try to hide or disable the upload box after a successful upload (using a callback and a state variable), the component is briefly hidden/disabled, but then immediately becomes visible/enabled again—even though the user has not interacted with the page. This makes it impossible to robustly control the upload flow for "one upload at a time" UX.
Steps to Reproduce:
Create a layout with a dcc.Upload and a callback that disables or hides the component after a successful upload.
Upload a file.
The component is hidden/disabled, but then reappears or is re-enabled without any user action.
Minimal Example:
import dash
from dash import html, dcc, Input, Output, State, no_update
app = dash.Dash(name)
app.layout = html.Div([
dcc.Store(id='upload-state', data='enabled'),
dcc.Upload(
id='upload-inference-file',
children=html.Div(['Drag and drop or ', html.A('select a file')]),
style={'width': '100%', 'height': '60px', 'lineHeight': '60px', 'borderWidth': '1px', 'borderStyle': 'dashed', 'borderRadius': '5px', 'textAlign': 'center', 'margin': '10px 0'},
disabled=False
),
html.Div(id='msg')
])
@app.callback(
Output('msg', 'children'),
Output('upload-inference-file', 'disabled'),
Input('upload-inference-file', 'filename'),
Input('upload-inference-file', 'contents'),
State('upload-state', 'data'),
prevent_initial_call=True
)
def upload_control(filename, contents, upload_state):
if not filename or not contents:
return no_update, no_update
return f'File {filename} uploaded!', True
if name == 'main':
app.run(debug=True)
Expected Behavior:
After a successful upload, the upload component should remain hidden or disabled until the user takes explicit action (such as clicking a reset button or refreshing the page).
Observed Behavior:
After a successful upload, the component is hidden or disabled for a moment, but then immediately becomes visible or enabled again, even though the user has not interacted with the page. This happens even in this minimal example, and makes it impossible to robustly enforce a "one upload at a time" workflow.
Additional Details:
This issue occurs even when using a dcc.Store to control the state and with all state logic isolated to the upload page.
The callback is sometimes triggered again with filename and contents as None, or with no explicit trigger, causing the component to be re-enabled.
The problem persists across browsers and after clearing cache.
The issue is present in both hiding (style={'display': 'none'}) and disabling (disabled=True) the component.
The problem occurs even when using no_update for all outputs if the trigger is not a new upload.
Environment:
Dash version: (please fill in, e.g., 2.15.0)
Browser: (please fill in, e.g., Chrome 125, Firefox 126)
OS: (please fill in, e.g., Ubuntu 22.04, Windows 10)
Python version: (please fill in, e.g., 3.10)
Why this matters:
This behavior makes it impossible to robustly control the upload flow for use cases where only one upload should be allowed at a time, or where the upload box should be hidden/disabled after a file is uploaded.