diff --git a/reflex/state.py b/reflex/state.py index 118dbc81b..4c6e8fec6 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -1290,7 +1290,6 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): if name in self.backend_vars: if self._backend_vars.get(name) == value: return - print(f"Setting {name} to {value}.") self._backend_vars.__setitem__(name, value) self.dirty_vars.add(name) self._mark_dirty() @@ -1830,11 +1829,13 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow): while dirty_vars: calc_vars, dirty_vars = dirty_vars, set() for cvar in self._dirty_computed_vars(from_vars=calc_vars): - self.dirty_vars.add(cvar) - dirty_vars.add(cvar) actual_var = self.computed_vars.get(cvar) if actual_var is not None: - actual_var.mark_dirty(instance=self) + changed = actual_var.mark_dirty(instance=self) + if not changed: + continue + self.dirty_vars.add(cvar) + dirty_vars.add(cvar) def _expired_computed_vars(self) -> set[str]: """Determine ComputedVars that need to be recalculated based on the expiration time. diff --git a/reflex/vars/base.py b/reflex/vars/base.py index b61b987e6..8444a29d0 100644 --- a/reflex/vars/base.py +++ b/reflex/vars/base.py @@ -2158,15 +2158,22 @@ class ComputedVar(Var[RETURN_TYPE]): self_is_top_of_stack = False return d - def mark_dirty(self, instance) -> None: + def mark_dirty(self, instance: BaseState) -> bool: """Mark this ComputedVar as dirty. Args: instance: the state instance that needs to recompute the value. + + Returns: + True if the value was marked dirty (has changed), False otherwise. """ - print(f"Marking {self._js_expr} as dirty") + cached_value = getattr(instance, self._cache_attr, None) + new_value = self.fget(instance) + if cached_value == new_value: + return False with contextlib.suppress(AttributeError): delattr(instance, self._cache_attr) + return True def _determine_var_type(self) -> Type: """Get the type of the var.