Repository: reflex-dev/reflex

Issue:
pydantic Field with rx.foreach on state broken
**Describe the bug**

Using pydantic Field in a state class fails with this error:

TypeError: You must provide an annotation for the state var `tag`. Annotation cannot be `typing.Any`.

IIRC this used to work and seems like a regression

**To Reproduce**

```python
from pydantic.v1 import Field
import reflex as rx


class Tag(rx.Base):
    name: str = ""


class State(rx.State):
    tags: list[Tag] = Field(default_factory=list)


def index() -> rx.Component:
    return rx.container(
        rx.foreach(
            State.tags,
            lambda tag: rx.text(tag.name),
        )
    )


app = rx.App()
app.add_page(index)
```

**Expected behavior**
no exception

**Specifics (please complete the following information):**
 - Python Version: 3.13
 - Reflex Version: main branch
 - OS: arch
 - Browser (Optional): --
 
**Additional context**
---



Discussion:
<p><a href="https://linear.app/reflex-dev/issue/ENG-4165/pydantic-field-on-state-broken">ENG-4165 pydantic Field on state broken</a></p>
@adhami3310 maybe we can add our own `default_factory` to `rx.field`?
> maybe we can add our own default_factory to rx.field

for now `rx.field` does nothing, it's empirical that we need to move off of pydantic for our state classes, but for now it will remain a noop

as for the issue itself, i'm not sure where this got broken, we should probably bisect it
The crux of the issue is that `rx.foreach` does not quite handle optional var type, and assigning to `Field` causes the annotation to be wrapped in an `Optional`. 



Patch:
diff --git a/reflex/state.py b/reflex/state.py
index c86bd9a1b74..f3491d3d5b2 100644
--- a/reflex/state.py
+++ b/reflex/state.py
@@ -1081,6 +1081,7 @@ def _set_default_value(cls, prop: Var):
         if (
             not field.required
             and field.default is None
+            and field.default_factory is None
             and not types.is_optional(prop._var_type)
         ):
             # Ensure frontend uses null coalescing when accessing.


Test patch:
diff --git a/tests/units/components/core/test_foreach.py b/tests/units/components/core/test_foreach.py
index 228165d3e1a..094f6029d72 100644
--- a/tests/units/components/core/test_foreach.py
+++ b/tests/units/components/core/test_foreach.py
@@ -1,8 +1,10 @@
 from typing import Dict, List, Set, Tuple, Union
 
+import pydantic.v1
 import pytest
 
 from reflex import el
+from reflex.base import Base
 from reflex.components.component import Component
 from reflex.components.core.foreach import (
     Foreach,
@@ -18,6 +20,12 @@
 from reflex.vars.sequence import ArrayVar
 
 
+class ForEachTag(Base):
+    """A tag for testing the ForEach component."""
+
+    name: str = ""
+
+
 class ForEachState(BaseState):
     """A state for testing the ForEach component."""
 
@@ -46,6 +54,8 @@ class ForEachState(BaseState):
     bad_annotation_list: list = [["red", "orange"], ["yellow", "blue"]]
     color_index_tuple: Tuple[int, str] = (0, "red")
 
+    default_factory_list: list[ForEachTag] = pydantic.v1.Field(default_factory=list)
+
 
 class ComponentStateTest(ComponentState):
     """A test component state."""
@@ -290,3 +300,11 @@ def test_foreach_component_state():
             ForEachState.colors_list,
             ComponentStateTest.create,
         )
+
+
+def test_foreach_default_factory():
+    """Test that the default factory is called."""
+    _ = Foreach.create(
+        ForEachState.default_factory_list,
+        lambda tag: text(tag.name),
+    )