Repository: reflex-dev/reflex

Issue:
Mixin computed vars are serialized multiple times
```python
import reflex as rx


class Mixin(rx.State, mixin=True):
    @rx.var
    def mixin_state(self) -> int:
        return 0


class UpperState(
    Mixin,
    rx.State,
):
    @rx.var
    def upper_state(self) -> int:
        return 0


class ChildState(UpperState):
    @rx.var
    def child_state(self) -> int:
        return 0


def test_dict():
    upper_state_name = UpperState.get_full_name()
    child_state_name = ChildState.get_full_name()
    expected_upper = {
        upper_state_name: {
            "upper_state": 0,
            "mixin_state": 0,
        },
        child_state_name: {
            "child_state": 0,
        },
    }
    upper = UpperState()
    assert upper.get_delta() == expected_upper
```

```
FAILED tests/test_it.py::test_dict - AssertionError: assert {'reflex___state____state.test_it____upper_state': {'mixin_state': 0, 'upper_state': 0}, 'reflex___state____state.test_it____upper_state.test_it____child_state': {'mixin_state': 0, 'child_state': 0}} == {'reflex___state____state.test_it____upper_state': {'upper_state': 0, 'mixin_state': 0}, 'reflex___state____state.test_it____upper_state.test_it____child_state': {'child_state': 0}}

  Common items:
  {'reflex___state____state.test_it____upper_state': {'mixin_state': 0,
                                                      'upper_state': 0}}
  Differing items:
  {'reflex___state____state.test_it____upper_state.test_it____child_state': {'child_state': 0, 'mixin_state': 0}} != {'reflex___state____state.test_it____upper_state.test_it____child_state': {'child_state': 0}}

  Full diff:
    {
        'reflex___state____state.test_it____upper_state': {
            'mixin_state': 0,
            'upper_state': 0,
        },
        'reflex___state____state.test_it____upper_state.test_it____child_state': {
            'child_state': 0,
  +         'mixin_state': 0,
        },
    }
```

thanks @abulvenz for reporting 


Discussion:

Patch:
diff --git a/reflex/state.py b/reflex/state.py
index 6712edd81b5..8a2a689f425 100644
--- a/reflex/state.py
+++ b/reflex/state.py
@@ -429,8 +429,9 @@ def _get_computed_vars(cls) -> list[Union[ComputedVar, ImmutableComputedVar]]:
         return [
             v
             for mixin in cls._mixins() + [cls]
-            for v in mixin.__dict__.values()
+            for name, v in mixin.__dict__.items()
             if isinstance(v, (ComputedVar, ImmutableComputedVar))
+            and name not in cls.inherited_vars
         ]
 
     @classmethod
@@ -558,6 +559,8 @@ def __init_subclass__(cls, mixin: bool = False, **kwargs):
 
         for mixin in cls._mixins():
             for name, value in mixin.__dict__.items():
+                if name in cls.inherited_vars:
+                    continue
                 if isinstance(value, (ComputedVar, ImmutableComputedVar)):
                     fget = cls._copy_fn(value.fget)
                     newcv = value._replace(


Test patch:
diff --git a/tests/test_state.py b/tests/test_state.py
index d34e771cb80..1d1db1b3fb1 100644
--- a/tests/test_state.py
+++ b/tests/test_state.py
@@ -3148,6 +3148,15 @@ class MixinState(State, mixin=True):
     num: int = 0
     _backend: int = 0
 
+    @rx.var(cache=True)
+    def computed(self) -> str:
+        """A computed var on mixin state.
+
+        Returns:
+            A computed value.
+        """
+        return ""
+
 
 class UsesMixinState(MixinState, State):
     """A state that uses the mixin state."""
@@ -3155,8 +3164,26 @@ class UsesMixinState(MixinState, State):
     pass
 
 
+class ChildUsesMixinState(UsesMixinState):
+    """A child state that uses the mixin state."""
+
+    pass
+
+
 def test_mixin_state() -> None:
     """Test that a mixin state works correctly."""
     assert "num" in UsesMixinState.base_vars
     assert "num" in UsesMixinState.vars
     assert UsesMixinState.backend_vars == {"_backend": 0}
+
+    assert "computed" in UsesMixinState.computed_vars
+    assert "computed" in UsesMixinState.vars
+
+
+def test_child_mixin_state() -> None:
+    """Test that mixin vars are only applied to the highest state in the hierarchy."""
+    assert "num" in ChildUsesMixinState.inherited_vars
+    assert "num" not in ChildUsesMixinState.base_vars
+
+    assert "computed" in ChildUsesMixinState.inherited_vars
+    assert "computed" not in ChildUsesMixinState.computed_vars