reflex-dev / reflex

πŸ•ΈοΈ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
19.88k stars 1.15k forks source link

Cannot `.mark_dirty` a ComputedVar directly in 0.6.0+ #4200

Open masenf opened 1 week ago

masenf commented 1 week ago

Describe the bug Because the computed var assigned to the State class isn't really a ComputedVar, but actually a ToOperation with a _js_expr based on the state, when _cache_attr is accessed to delete it (in mark_dirty), it returns the wrong attribute and doesn't actually clear the cache.

To Reproduce

import datetime

import reflex as rx

class State(rx.State):
    @rx.var(cache=True)
    def dt(self) -> datetime.datetime:
        return datetime.datetime.now()

    def dt_reset(self):
        type(self).dt.mark_dirty(self)
        self.dirty_vars.add("dt")
        self._mark_dirty()

def index() -> rx.Component:
    # Welcome Page (Index)
    return rx.container(
        rx.color_mode.button(position="top-right"),
        rx.vstack(
            rx.heading(State.dt),
            rx.button("Reset Cache", on_click=State.dt_reset),
        ),
        rx.logo(),
    )

app = rx.App()
app.add_page(index)

Expected behavior In reflex 0.5.10, each time the Reset Cache button is clicked, the timestamp updates.

In reflex 0.6.0, nothing happens.

Specifics (please complete the following information):

Additional context I think the _cache_attr should be based on some data intrinsic to the ComputedVar, not something that could be changed downstream by some operation

linear[bot] commented 1 week ago

ENG-3964 Cannot `.mark_dirty` a ComputedVar directly in 0.6.0+

masenf commented 1 week ago

As a workaround, it seems you can do self.computed_vars["dt"].mark_dirty(self) 😁

adhami3310 commented 6 days ago

generally speaking, it's hard to make this work all the time, what if the computed var was an object and doing .make_dirty on it would result on that field itself like obj['make_dirty'], in which case this operation isn't coherent