Improve ClientState compatibility with rx.input (#3490)

* Ignore type checking for generic aliases in _var_name_unwrapped

* Allow ClientStateVar.set_value to be used with text inputs

* client_state: If var_name is not provided, create a random name

* client_state: partition the arg value to get `_e0` from `_e0.target.value`
This commit is contained in:
Masen Furer 2024-06-19 07:01:46 -07:00 committed by GitHub
parent 0d39237b3c
commit ffb24ceeee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 17 additions and 14 deletions

View File

@ -92,7 +92,7 @@ class Input(ChakraComponent):
Returns:
The component.
"""
if props.get("value") is not None and props.get("on_change"):
if props.get("value") is not None and props.get("on_change") is not None:
# create a debounced input if the user requests full control to avoid typing jank
return DebounceInput.create(super().create(*children, **props))
return super().create(*children, **props)

View File

@ -73,7 +73,7 @@ class TextArea(ChakraComponent):
Returns:
The component.
"""
if props.get("value") is not None and props.get("on_change"):
if props.get("value") is not None and props.get("on_change") is not None:
# create a debounced input if the user requests full control to avoid typing jank
return DebounceInput.create(super().create(*children, **props))
return super().create(*children, **props)

View File

@ -107,7 +107,7 @@ class TextArea(RadixThemesComponent, elements.Textarea):
Returns:
The component.
"""
if props.get("value") is not None and props.get("on_change"):
if props.get("value") is not None and props.get("on_change") is not None:
# create a debounced input if the user requests full control to avoid typing jank
return DebounceInput.create(super().create(*children, **props))
return super().create(*children, **props)

View File

@ -100,7 +100,7 @@ class TextFieldRoot(elements.Div, RadixThemesComponent):
The component.
"""
component = super().create(*children, **props)
if props.get("value") is not None and props.get("on_change"):
if props.get("value") is not None and props.get("on_change") is not None:
# create a debounced input if the user requests full control to avoid typing jank
return DebounceInput.create(component)
return component

View File

@ -9,7 +9,7 @@ from typing import Any, Callable, Optional, Type, Union
from reflex import constants
from reflex.event import EventChain, EventHandler, EventSpec, call_script
from reflex.utils.imports import ImportVar
from reflex.vars import Var, VarData
from reflex.vars import Var, VarData, get_unique_variable_name
NoValue = object()
@ -75,7 +75,10 @@ class ClientStateVar(Var):
@classmethod
def create(
cls, var_name: str, default: Any = NoValue, global_ref: bool = True
cls,
var_name: str | None = None,
default: Any = NoValue,
global_ref: bool = True,
) -> "ClientStateVar":
"""Create a local_state Var that can be accessed and updated on the client.
@ -102,6 +105,8 @@ class ClientStateVar(Var):
Returns:
ClientStateVar
"""
if var_name is None:
var_name = get_unique_variable_name()
assert isinstance(var_name, str), "var_name must be a string."
if default is NoValue:
default_var = Var.create_safe("", _var_is_local=False, _var_is_string=False)
@ -189,7 +194,7 @@ class ClientStateVar(Var):
# This is a hack to make it work like an EventSpec taking an arg
value = Var.create_safe(value, _var_is_string=isinstance(value, str))
if not value._var_is_string and value._var_full_name.startswith("_"):
arg = value._var_name_unwrapped
arg = value._var_name_unwrapped.partition(".")[0]
else:
arg = ""
setter = f"({arg}) => {setter}({value._var_name_unwrapped})"

View File

@ -1792,18 +1792,16 @@ class Var:
"""
from reflex.style import Style
type_ = (
get_origin(self._var_type)
if types.is_generic_alias(self._var_type)
else self._var_type
)
generic_alias = types.is_generic_alias(self._var_type)
type_ = get_origin(self._var_type) if generic_alias else self._var_type
wrapped_var = str(self)
return (
wrapped_var
if not self._var_state
and types._issubclass(type_, dict)
or types._issubclass(type_, Style)
and not generic_alias
and (types._issubclass(type_, dict) or types._issubclass(type_, Style))
else wrapped_var.strip("{}")
)