[ENG-4165] Consider default and default_factory for state vars (#4510)

* [ENG-4165] Consider default and default_factory for state vars

When determining whether a state var should be marked as optional, check that
it is missing both default and default_factory and is not required.

Fix #4471

* add test for default factory with rx.foreach (#4515)

---------

Co-authored-by: benedikt-bartscher <31854409+benedikt-bartscher@users.noreply.github.com>
This commit is contained in:
Masen Furer 2024-12-12 10:10:44 -08:00 committed by GitHub
parent 1b6f539657
commit adfda8adfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 0 deletions

View File

@ -1097,6 +1097,7 @@ class BaseState(Base, ABC, extra=pydantic.Extra.allow):
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.

View File

@ -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.number import NumberVar
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),
)