-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
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:
on_mountonly fires once during initial render- There's no
on_props_changeor similar lifecycle event - 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
- Radio Group: Accepts
dictorlist, needs to normalize to internal format and update when options change - Editable Table: Takes
dataandcolumnsprops, needs to rebuild internal state when these change
Environment
- Reflex Version: (latest)
- Python Version: 3.10+