Skip to content
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

[BUG] Dash 3 Components as Props #3234

Open
BSd3v opened this issue Mar 21, 2025 · 6 comments
Open

[BUG] Dash 3 Components as Props #3234

BSd3v opened this issue Mar 21, 2025 · 6 comments
Assignees
Labels
bug something broken dash-3.0 Going in dash-3.0 release. P1 needed for current cycle

Comments

@BSd3v
Copy link
Contributor

BSd3v commented Mar 21, 2025

When components are props are unmounted, they dont unmount properly

@BSd3v
Copy link
Contributor Author

BSd3v commented Mar 21, 2025

Run this example:



import dash_mantine_components as dmc
from dash import Output, Input, html, callback, Dash, ctx, _dash_renderer
from dash.exceptions import PreventUpdate
from dash_iconify import DashIconify

# this is optional when using dash >3.0.0
_dash_renderer._set_react_version("18.2.0")

app = Dash(__name__, external_stylesheets=dmc.styles.ALL)

app.layout = dmc.MantineProvider(
    [
        dmc.NotificationProvider(),
        html.Div(id="notify-container"),
        dmc.Group(
            children=[
                dmc.Button(
                    "Load Data",
                    id="show-notification",
                ),
                dmc.Button(
                    "Update",
                    id="update-notification",
                ),
            ],
        ),
    ],
)


@callback(
    Output("notify-container", "children"),
    Input("show-notification", "n_clicks"),
    Input("update-notification", "n_clicks"),
    prevent_initial_call=True,
)
def notify(nc1, nc2):
    if not ctx.triggered:
        raise PreventUpdate
    else:
        button_id = ctx.triggered_id
        if "show" in button_id:
            return dmc.Notification(
                id="my-notification",
                title="Process initiated",
                message="The process has started.",
                loading=True,
                color="orange",
                action="show",
                autoClose=False,
            )
        else:
            return dmc.Notification(
                id="my-notification",
                title="Data loaded",
                message="Notification closing in 2 seconds",
                color="green",
                loading=False,
                action="update",
                autoClose=2000,
                icon=DashIconify(icon="akar-icons:circle-check"),
            )
app.clientside_callback(
    """(c) => {
        if (c) {
            setTimeout(() => dash_clientside.set_props('notify-container', {children: []}, 2000))
        }
    }""",
    Input('notify-container', 'children')
)


if __name__ == "__main__":
    app.run(debug=True)

click show and then try to update, and you will encounter the issue. It freezes everything for me. I believe the issue comes from the Icon which is set as React.ReactNode

@BSd3v
Copy link
Contributor Author

BSd3v commented Mar 23, 2025

From what I can tell, it happens when removing a parent element that contains one of these node components.

The icon in notification is a react node which is dash iconify.

And to clarify, the issue points to the selector that listens to redux for state changes.

@CNFeffery
Copy link
Contributor

If it's regarding component-type parameters, I haven't been able to reproduce such issues in the fac (>=0.4.0rc1) adapted for dash 3.0.

dash                           3.0.0
feffery_antd_components        0.4.0rc1

import dash
from dash import html
import feffery_antd_components as fac
from feffery_dash_utils.style_utils import style
from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

app.layout = html.Div(
    [
        fac.AntdButton("button-demo", id="button-demo"),
        html.Div(
            fac.AntdButton(icon=fac.AntdIcon(icon="antd-eye")), id="button-container"
        ),
    ],
    style=style(padding=50),
)


@app.callback(
    Output("button-container", "children"),
    Input("button-demo", "nClicks"),
    State("button-container", "children"),
    prevent_initial_call=True,
)
def update_icon(nClicks, icon):
    return (
        fac.AntdButton(icon=fac.AntdIcon(icon="antd-eye-invisible"))
        if icon["props"]["icon"]["props"]["icon"] == "antd-eye"
        else fac.AntdButton(icon=fac.AntdIcon(icon="antd-eye"))
    )


if __name__ == "__main__":
    app.run(debug=True)

Image

@CNFeffery
Copy link
Contributor

From what I can tell, it happens when removing a parent element that contains one of these node components.

The icon in notification is a react node which is dash iconify.

I've updated the test examples. Not sure if it's similar to the callback update scenario you described.

@BSd3v
Copy link
Contributor Author

BSd3v commented Mar 23, 2025

@CNFeffery it would be like removing the button-container from the dash tree.

For example, if I remove the icon from the component in my callback for the notification, it works. But add the icon and it breaks.

@T4rk1n T4rk1n self-assigned this Mar 24, 2025
@T4rk1n T4rk1n added bug something broken dash-3.0 Going in dash-3.0 release. P1 needed for current cycle labels Mar 24, 2025
@BSd3v
Copy link
Contributor Author

BSd3v commented Mar 31, 2025

I believe that my PR may address this: #3248

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken dash-3.0 Going in dash-3.0 release. P1 needed for current cycle
Projects
None yet
Development

No branches or pull requests

3 participants