-
Consider: import time
from idom import use_state, html, component
@component
def main():
(text, update) = use_state("initial")
def on_change(event):
time.sleep(0.1) # heavy-duty sleeping
update(event['target']['value'])
return html.div(
html.input({'value': text, 'onChange': on_change}),
html.div(text),
) This results in a (usually unnecessary) pile-up of onChange events, and with more complexity can break the "input experience" altogether. Can this be avoided client-side without explicit JS? For example, only notify the server 300ms after the change, unless overwritten by a new event. On a similar note, what would be a good way to schedule a cancellable component rerun/rerender (if I want to handle the pile-up server-side, among other usecases)? Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
This is my current solution (in django context). The import asyncio
import time
from django_idom.hooks import use_mutation
from idom import use_state, html, component, use_ref
def delay_latest(f):
def process():
while queue.qsize():
if queue.qsize() >= 2:
queue.get_nowait()
return
if (delayed_f := queue.get_nowait()):
delayed_f()
queue = use_ref(asyncio.Queue()).current
mutation = use_mutation(process)
async def _(event):
queue.put_nowait(f(event))
await asyncio.sleep(1)
mutation.execute()
return _
@component
def main():
(text, set_text) = use_state("initial")
(status, set_status) = use_state(None)
@delay_latest
def on_change(event):
set_text(event['target']['value'])
def delayed():
set_status(f"Processing: `{event['target']['value']}`")
time.sleep(3)
set_status(f"Done with: `{event['target']['value']}`")
return delayed
return html.div(
html.input({'value': text, 'onChange': on_change}),
html.div(f"Status: {status}"),
) |
Beta Was this translation helpful? Give feedback.
-
From my reading, there two separate questions here:
The answer to both is that there is no way to do either at present. I'll address each individually and, with a complete example, below... For 1, given that you cannot configure any client-side waiting behavior, you'd want to implement this logic server-side. I don't think we'd want to add the ability to configure the client's behavior in this regard simply to avoid adding custom props (e.g. an For 2, React does not supply a built-in way to cancel a scheduled render, and for this reason, neither does IDOM. With that said, in your case there are two ways to reduce the number of server-side renders you perform. First, you can use an uncontrolled input (this is not documents in IDOM right now unfortunately). So for an Here's an example that implements all the suggested improvements: import asyncio
from idom import component, html, run, use_ref, use_state, use_callback
@component
def example():
slow, set_slow = use_delayed_state("", delay=3)
return html._(
html.input({"onChange": lambda event: set_slow(event["target"]["value"])}),
html.p("Slow value is: ", slow),
)
def use_delayed_state(initial, delay):
state, set_state = use_state(initial)
use_delayed_state = use_delayed_callback(set_state, delay)
return state, use_delayed_state
def use_delayed_callback(func, delay):
task = use_ref(None)
@use_callback
async def delayed_wrapper(*args, **kwargs):
await asyncio.sleep(delay)
func(*args, **kwargs)
@use_callback
def callback(*args, **kwargs) -> None:
last_task = task.current
if last_task is not None and not last_task.done():
last_task.cancel()
task.current = asyncio.create_task(delayed_wrapper(*args, **kwargs))
return callback
run(example) |
Beta Was this translation helpful? Give feedback.
-
One unrelated suggestion, you should run Flake8 plugin against your code. It will help to enforce the "Rules of Hooks" (another section of the docs that needs a bit of help).
|
Beta Was this translation helpful? Give feedback.
From my reading, there two separate questions here:
The answer to both is that there is no way to do either at present. I'll address each individually and, with a complete example, below...
For 1, given that you cannot configure any client-side waiting behavior, you'd want to implement this logic server-side. I don't think we'd want to add the ability to configure the client's behavior in this regard simply to avoid adding custom props (e.g. an
onChangeDelay
prop) to standard …