80 releases
0.7.0-preview2 | Apr 29, 2024 |
---|---|
0.6.15 | Sep 8, 2024 |
0.6.13 | Jul 24, 2024 |
0.6.9 | Mar 4, 2024 |
0.0.19 | Nov 27, 2022 |
#1874 in Web programming
45,414 downloads per month
Used in 178 crates
(11 directly)
405KB
8K
SLoC
The reactive system for the Leptos Web framework.
Fine-Grained Reactivity
Leptos is built on a fine-grained reactive system, which means that individual reactive values (“signals,” sometimes known as observables) trigger the code that reacts to them (“effects,” sometimes known as observers) to re-run. These two halves of the reactive system are inter-dependent. Without effects, signals can change within the reactive system but never be observed in a way that interacts with the outside world. Without signals, effects run once but never again, as there’s no observable value to subscribe to.
Here are the most commonly-used functions and types you'll need to build a reactive system:
Signals
- Signals:
create_signal
, which returns a (ReadSignal
,WriteSignal
tuple, orcreate_rw_signal
, which returns a signalRwSignal
without this read-write segregation. - Derived Signals: any function that relies on another signal.
- Memos:
create_memo
, which returns aMemo
. - Resources:
create_resource
, which converts anasync
Future
into a synchronousResource
signal. - Triggers:
create_trigger
, creates a purely reactiveTrigger
primitive without any associated state.
Effects
- Use
create_effect
when you need to synchronize the reactive system with something outside it (for example: logging to the console, writing to a file or local storage) - The Leptos DOM renderer wraps any [
Fn
] in your template withcreate_effect
, so components you write do not need explicit effects to synchronize with the DOM.
Example
use leptos_reactive::*;
// creates a new reactive runtime
// this is omitted from most of the examples in the docs
// you usually won't need to call it yourself
let runtime = create_runtime();
// a signal: returns a (getter, setter) pair
let (count, set_count) = create_signal(0);
// calling the getter gets the value
// can be `count()` on nightly
assert_eq!(count.get(), 0);
// calling the setter sets the value
// can be `set_count(1)` on nightly
set_count.set(1);
// or we can mutate it in place with update()
set_count.update(|n| *n += 1);
// a derived signal: a plain closure that relies on the signal
// the closure will run whenever we *access* double_count()
let double_count = move || count.get() * 2;
assert_eq!(double_count(), 4);
// a memo: subscribes to the signal
// the closure will run only when count changes
let memoized_triple_count = create_memo(move |_| count.get() * 3);
// can be `memoized_triple_count()` on nightly
assert_eq!(memoized_triple_count.get(), 6);
// this effect will run whenever `count` changes
create_effect(move |_| {
println!("Count = {}", count.get());
});
// disposes of the reactive runtime
runtime.dispose();
Dependencies
~4–13MB
~161K SLoC