Skip to content

ComponentState Lacks Dynamic Updates From External States #6153

@MatthewCollinsNZ

Description

@MatthewCollinsNZ

ComponentState Lacks Dynamic Updates From External States

Summary

ComponentState does not provide a built-in mechanism for updating internal state when props passed from external state change at runtime. This requires cumbersome workarounds using on_mount events that only capture initial values and don't respond to subsequent changes.

Current Behavior

When building reusable components with ComponentState, there's no way to make the component's internal state react to changes in props passed from external state. Class methods only compile once and do not update during the app's runtime when external state changes.

Example: Radio Group Component

class RadioGroup(rx.ComponentState):
    """Radio group that accepts either Dict[value, display_value] or list[values]"""
    options_dict: dict[str, str]
    value: str

    @rx.event
    def set_options(self, options: dict[str, str] | list[str]):
        """Set options - but how do we trigger this when external options change?"""
        if isinstance(options, list):
            self.options_dict = {item: item for item in options}
        else:
            self.options_dict = options

    @rx.event
    def set_value(self, value):
        self.value = value

    @rx.var
    def display_value(self) -> str:
        """The currently selected display value."""
        return self.options_dict.get(self.value, "")

    @classmethod
    def get_component(cls, options: dict[str, str], value: rx.Var, **props):
        return rx.radio(
            items=list(options.values()),
            value=cls.display_value,
            # Current workaround: use on_mount to set initial values
            on_mount=[lambda: cls.set_options(options), lambda: cls.set_value(value)],
        )

Problem: When options changes in the external state after initial mount, the RadioGroup component's internal options_dict doesn't update because:

  1. on_mount only fires once during initial render
  2. There's no on_props_change or similar lifecycle event
  3. Class methods can't access reactive vars

Expected Behavior

ComponentState should provide a way to react to prop changes. This would allow components to reactively transform props into internal state whenever those props change in the external state.

Use Cases

This affects any ComponentState component that needs to:

  • Transform or validate props before use (e.g., accepting multiple input formats)
  • Maintain derived state based on props (e.g., filtered lists, computed values)
  • Sync with external state changes (e.g., dropdowns that update when parent options change)

Real-World Examples from Our Codebase

  1. Radio Group: Accepts dict or list, needs to normalize to internal format and update when options change
  2. Editable Table: Takes data and columns props, needs to rebuild internal state when these change

Environment

  • Reflex Version: (latest)
  • Python Version: 3.10+

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions