reflex-dev / reflex

🕸️ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
19.34k stars 1.1k forks source link

on_unmount doesn't work #3329

Open iBuitron opened 4 months ago

iBuitron commented 4 months ago

Describe the bug as you view on rx.cond

Note: is_upload = False (but use ~ on cond)
True: mount -> _upload
False: mount -> rx.fragment

when i upload a file, it trigger on_drop, so is_upload change to True

Now the rx.cond should render the rx.fragment, as my understand this unMount the _upload so it should call his on_unmount calling the rx.redirect to the path.

But, in prod mode this doens't call the on_unmount in _upload

To Reproduce Steps to reproduce the behavior:

class Upload(rx.ComponentState):
    _data: bytes | list[bytes]
    is_upload: bool = False

    async def upload_single(self, upload_files: list[rx.UploadFile]):
        if upload_files:
            upload_data = await upload_files[0].read()
            print(upload_files[0].filename)
            self._data = upload_data
            self.is_upload = True

    async def upload_multiple(self, upload_files: list[rx.UploadFile]):
        if upload_files:
            upload_data = [await file.read() for file in upload_files]

            self._data = upload_data
            self.is_upload = True

    @classmethod
    def get_component(
        cls,
        id: str,
        select_files: Literal["single", "multiple"],
        redirect_path: str = "",
    ) -> rx.Component:
        _upload = rx.upload(
            rx.vstack(
                rx.text("Drag and drop files here or click to select files"),
            ),
            id=id,
            on_drop=getattr(cls, f"upload_{select_files}")(
                rx.upload_files(upload_id=id)
            ),
            multiple=True if select_files == "multiple" else False,
            on_unmount=rx.redirect(redirect_path),
        )

        new_upload = rx.box(
            rx.cond(
                ~cls.is_upload,
                _upload,
                rx.fragment(
                    "Redirecting",
                ),
            )
        )

        return new_upload
iBuitron commented 4 months ago

cond calls the redirect on load the page.

class Upload(rx.ComponentState):
    _data: bytes | list[bytes]
    show_upload: bool = True

    async def upload_single(self, upload_files: list[rx.UploadFile]):
        if upload_files:
            upload_data = await upload_files[0].read()

            self._data = upload_data
            self.show_upload = False

    async def upload_multiple(self, upload_files: list[rx.UploadFile]):
        if upload_files:
            upload_data = [await file.read() for file in upload_files]

            self._data = upload_data
            self.show_upload = False

    @classmethod
    def get_component(
        cls,
        id: str,
        select_files: Literal["single", "multiple"],
        redirect_path: str = "",
    ) -> rx.Component:
        _upload = rx.upload(
            rx.vstack(
                rx.text("Drag and drop files here or click to select files"),
            ),
            id=id,
            on_drop=getattr(cls, f"upload_{select_files}")(
                rx.upload_files(upload_id=id)
            ),
            multiple=True if select_files == "multiple" else False,

        )

        new_upload = rx.box(
            rx.cond(
                cls.show_upload,
                _upload,
                rx.fragment(
                    "Redirecting", on_mount=rx.redirect(redirect_path, external=False)
                ),
            )
        )

        return new_upload