reflex
reflex copied to clipboard
Input example w/ Clear button loses characters
Describe the bug When you control the text of a field, the server does not save the text fast enough.
To Reproduce
- https://pynecone.io/docs/library/forms/input
- Use the 3rd input box, the one with a clear button.
- If you type fast enough, it saves some but not everything of what you type
Expected behavior I'd expect it to save everything I type.
Screenshots https://youtu.be/k9_lFsbLUB4
Specifics (please complete the following information):
- Python Version:
- Pynecone Version:
- OS: macOS 13.1
- Browser (Optional): Firefox 110.0.1 (64-bit)
Additional context
I've tested this locally, with a very simple single-page pynecone app (less than 100 lines total), and this seems to work as you'd expect it. Possibly because the help docs are bigger and more complicated? But it seems like maybe it is overkill to need to set_text and build the var/function... just to have a clear button?
Did some more research, and I found the on_key_down / on_key_up input example is more reliably slow. This is me typing "asdf" and backspace (repeatedly). https://youtu.be/t-zgIu6tqcw - This was recorded in Brave Browser, but I also tested Firefox & Chrome. Also tested in private mode with all extensions disabled with the same result.
Initially I was experimenting with figuring out how to capture enter and only enter. Since it seems to capture any meta keys, including backspace.
Got it thanks for taking a look, I'll do some profiling on this tomorrow can post what I find it should be fast. Are you just using pc run or pc run --env prod? Dev mode is slower than prod maybe causing this
Locally I ran pc run, no prod. But the videos were from the official pynecone.io docs.
While investigating this issue, I found that the fix for #632 aims to alleviate the sort of problem seen here, but I haven't been able to get it working yet.
As an interim solution for having nice form inputs, I ended up wrapping react-debounce-input to great effect. The benefits are less websocket roundtrips and automatic blur/enter triggering on onChange.
Here is my sample code, which allows comparing the direct control and debounced control behavior. (edit: fixed the custom_code by overriding get_imports)
"""A debounced input example"""
import asyncio
import typing as t
import pynecone as pc
from pynecone.utils.imports import ImportDict
from pynecone.var import Var
class DebouncedInput(pc.Input):
library = "react-debounce-input"
tag = "DebounceInput"
element: Var = Var.create("{Input}", is_local=False, is_string=False)
debounceTimeout: int = 500
def get_imports(self) -> ImportDict:
imports = super().get_imports()
for library, import_set in pc.Input().get_imports().items():
imports.setdefault(library, set()).update(import_set)
return imports
class State(pc.State):
text_value: str = ""
async def set_text_value(self, v: str):
# simulate a slow autocomplete lookup, for example
await asyncio.sleep(0.3)
self.text_value = v
def clear_text_value(self):
self.text_value = ""
def index() -> pc.Component:
return pc.center(
pc.vstack(
pc.hstack(
pc.text("Direct Control"),
pc.input(value=State.text_value, on_change=State.set_text_value)
),
pc.hstack(
pc.text("Debounced Control"),
DebouncedInput.create(
value=State.text_value,
on_change=State.set_text_value,
),
),
pc.button("Clear", on_click=State.clear_text_value),
pc.text("Value Is: '", State.text_value, "'")
),
padding_top="10%",
)
# Add state and page to the app.
app = pc.App(state=State)
app.add_page(index)
app.compile()
Be sure to include the library in pcconfig.py
import pynecone as pc
config = pc.Config(
app_name="controlled_input",
frontend_packages=[
"react-debounce-input", # <----
],
db_url="sqlite:///pynecone.db",
env=pc.Env.DEV,
)