mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
examples: add timer example with reactive use_interval
hook (#925)
This commit is contained in:
parent
72f8bf4e20
commit
9badfa997b
9 changed files with 124 additions and 0 deletions
|
@ -24,6 +24,7 @@ CARGO_MAKE_CRATE_WORKSPACE_MEMBERS = [
|
|||
"ssr_modes_axum",
|
||||
"tailwind",
|
||||
"tailwind_csr_trunk",
|
||||
"timer",
|
||||
"todo_app_sqlite",
|
||||
"todo_app_sqlite_axum",
|
||||
"todo_app_sqlite_viz",
|
||||
|
|
24
examples/timer/Cargo.toml
Normal file
24
examples/timer/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[package]
|
||||
name = "timer"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
|
||||
[dependencies]
|
||||
leptos = { path = "../../leptos" }
|
||||
console_log = "1"
|
||||
log = "0.4"
|
||||
console_error_panic_hook = "0.1.7"
|
||||
wasm-bindgen = "0.2"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3"
|
||||
features = [
|
||||
"Window",
|
||||
]
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.0"
|
9
examples/timer/Makefile.toml
Normal file
9
examples/timer/Makefile.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[tasks.build]
|
||||
command = "cargo"
|
||||
args = ["+nightly", "build-all-features"]
|
||||
install_crate = "cargo-all-features"
|
||||
|
||||
[tasks.check]
|
||||
command = "cargo"
|
||||
args = ["+nightly", "check-all-features"]
|
||||
install_crate = "cargo-all-features"
|
7
examples/timer/README.md
Normal file
7
examples/timer/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Leptos Timer Example
|
||||
|
||||
This example creates a simple timer based on `setInterval` in a client side rendered app with Rust and WASM.
|
||||
|
||||
To run it, just issue the `trunk serve --open` command in the example root. This will build the app, run it, and open a new browser to serve it.
|
||||
|
||||
> If you don't have `trunk` installed, [click here for install instructions.](https://trunkrs.dev/)
|
8
examples/timer/index.html
Normal file
8
examples/timer/index.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link data-trunk rel="rust" data-wasm-opt="z"/>
|
||||
<link data-trunk rel="icon" type="image/ico" href="/public/favicon.ico"/>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
BIN
examples/timer/public/favicon.ico
Normal file
BIN
examples/timer/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
2
examples/timer/rust-toolchain.toml
Normal file
2
examples/timer/rust-toolchain.toml
Normal file
|
@ -0,0 +1,2 @@
|
|||
[toolchain]
|
||||
channel = "nightly"
|
61
examples/timer/src/lib.rs
Normal file
61
examples/timer/src/lib.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use leptos::{leptos_dom::helpers::IntervalHandle, *};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Timer example, demonstrating the use of `use_interval`.
|
||||
#[component]
|
||||
pub fn TimerDemo(cx: Scope) -> impl IntoView {
|
||||
// count_a updates with a fixed interval of 1000 ms, whereas count_b has a dynamic
|
||||
// update interval.
|
||||
let (count_a, set_count_a) = create_signal(cx, 0_i32);
|
||||
let (count_b, set_count_b) = create_signal(cx, 0_i32);
|
||||
|
||||
let (interval, set_interval) = create_signal(cx, 1000);
|
||||
|
||||
use_interval(cx, 1000, move || {
|
||||
set_count_a.update(|c| *c = *c + 1);
|
||||
});
|
||||
use_interval(cx, interval, move || {
|
||||
set_count_b.update(|c| *c = *c + 1);
|
||||
});
|
||||
|
||||
view! { cx,
|
||||
<div>
|
||||
<div>"Count A (fixed interval of 1000 ms)"</div>
|
||||
<div>{count_a}</div>
|
||||
<div>"Count B (dynamic interval, currently " {interval} " ms)"</div>
|
||||
<div>{count_b}</div>
|
||||
<input prop:value=interval on:input=move |ev| {
|
||||
if let Ok(value) = event_target_value(&ev).parse::<u64>() {
|
||||
set_interval(value);
|
||||
}
|
||||
}/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
/// Hook to wrap the underlying `setInterval` call and make it reactive w.r.t.
|
||||
/// possible changes of the timer interval.
|
||||
pub fn use_interval<T, F>(cx: Scope, interval_millis: T, f: F)
|
||||
where
|
||||
F: Fn() + Clone + 'static,
|
||||
T: Into<MaybeSignal<u64>> + 'static,
|
||||
{
|
||||
let interval_millis = interval_millis.into();
|
||||
create_effect(cx, move |prev_handle: Option<IntervalHandle>| {
|
||||
// effects get their previous return value as an argument
|
||||
// each time the effect runs, it will return the interval handle
|
||||
// so if we have a previous one, we cancel it
|
||||
if let Some(prev_handle) = prev_handle {
|
||||
prev_handle.clear();
|
||||
};
|
||||
|
||||
// here, we return the handle
|
||||
set_interval_with_handle(
|
||||
f.clone(),
|
||||
// this is the only reactive access, so this effect will only
|
||||
// re-run when the interval changes
|
||||
Duration::from_millis(interval_millis.get()),
|
||||
)
|
||||
.expect("could not create interval")
|
||||
});
|
||||
}
|
12
examples/timer/src/main.rs
Normal file
12
examples/timer/src/main.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
use leptos::*;
|
||||
use timer::TimerDemo;
|
||||
|
||||
pub fn main() {
|
||||
_ = console_log::init_with_level(log::Level::Debug);
|
||||
console_error_panic_hook::set_once();
|
||||
mount_to_body(|cx| {
|
||||
view! { cx,
|
||||
<TimerDemo />
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue