-
I am implementing search that happens as the user types. I want to delay the search until after the user has stopped typing for some small amount of time so that the search requests are not issued too frequently to the server. I am using SSR and Here is my attempt: use gloo_timers::callback::Timeout;
use leptos::*;
#[component]
pub fn Search(cx: Scope) -> impl IntoView {
let (q, set_q) = create_signal(cx, String::new());
let (q_delayed, set_q_delayed) = create_signal(cx, q.get_untracked());
// Add a delay so that the search happens when a key has _not_ been pressed for the
// delay period
create_effect(cx, move |to: Option<Timeout>| {
if let Some(t) = to {
t.cancel();
}
let value = q();
Timeout::new(SEARCH_DELAY_MS, move || {
set_q_delayed(value);
})
});
let search_results = create_resource(cx, q_delayed, move |q| search(cx, q));
view! {
// View code
}
}
async fn search(cx: Scope, q: String) -> Option<Vec<SearchResult>> {
if &q == "" {
return Some(vec![]);
}
let mut path = // create path to search endpoint with query params
let results = api_client::fetch(cx, &path).await;
results.map(|r| r.results)
} When I run
I tried changing I get the sense that my approach here is not working well with the reactive system. What is the best way to implement this in leptos? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
I wonder if the problem is actually coming from somewhere else in your code. I added stubs for a few bits that were missing from your sample, and is seems to work as intended. You wrote a pretty elegant debounce, here! use gloo_timers::callback::Timeout;
#[component]
pub fn Search(cx: Scope) -> impl IntoView {
let (q, set_q) = create_signal(cx, String::new());
let (q_delayed, set_q_delayed) = create_signal(cx, q.get_untracked());
// Add a delay so that the search happens when a key has _not_ been pressed for the
// delay period
create_effect(cx, move |to: Option<Timeout>| {
if let Some(t) = to {
t.cancel();
}
let value = q();
Timeout::new(500, move || {
set_q_delayed(value);
})
});
let search_results = create_resource(cx, q_delayed, move |q| search(cx, q));
view! { cx,
<input on:input=move |ev| set_q(event_target_value(&ev)) value=q/>
<pre>{move || search_results.read().map(|v| format!("{v:?}"))}</pre>
}
}
async fn search(cx: Scope, q: String) -> Option<Vec<String>> {
if &q == "" {
Some(vec![])
}
else {
gloo_timers::future::TimeoutFuture::new(250).await;
Some(vec![q.to_string()])
}
} EDIT: Actually make sure you are on the latest version, which is now |
Beta Was this translation helpful? Give feedback.
I wonder if the problem is actually coming from somewhere else in your code. I added stubs for a few bits that were missing from your sample, and is seems to work as intended. You wrote a pretty elegant debounce, here!