pub struct Memo<T>where
T: 'static,{ /* private fields */ }Expand description
An efficient derived reactive value based on other reactive values.
Unlike a “derived signal,” a memo comes with two guarantees:
- The memo will only run once per change, no matter how many times you access its value.
- The memo will only notify its dependents if the value of the computation changes.
This makes a memo the perfect tool for expensive computations.
Memos have a certain overhead compared to derived signals. In most cases, you should create a derived signal. But if the derivation calculation is expensive, you should create a memo.
As with create_effect, the argument to the memo function is the previous value,
i.e., the current value of the memo, which will be None for the initial calculation.
Core Trait Implementations
.get()(or calling the signal as a function) clones the current value of the signal. If you call it within an effect, it will cause that effect to subscribe to the signal, and to re-run whenever the value of the signal changes..get_untracked()clones the value of the signal without reactively tracking it.
.with()allows you to reactively access the signal’s value without cloning by applying a callback function..with_untracked()allows you to access the signal’s value without reactively tracking it.
.to_stream()converts the signal to anasyncstream of values.
Examples
let (value, set_value) = create_signal(0);
// 🆗 we could create a derived signal with a simple function
let double_value = move || value.get() * 2;
set_value.set(2);
assert_eq!(double_value(), 4);
// but imagine the computation is really expensive
let expensive = move || really_expensive_computation(value.get()); // lazy: doesn't run until called
create_effect(move |_| {
// 🆗 run #1: calls `really_expensive_computation` the first time
log::debug!("expensive = {}", expensive());
});
create_effect(move |_| {
// ❌ run #2: this calls `really_expensive_computation` a second time!
let value = expensive();
// do something else...
});
// instead, we create a memo
// 🆗 run #1: the calculation runs once immediately
let memoized = create_memo(move |_| really_expensive_computation(value.get()));
create_effect(move |_| {
// 🆗 reads the current value of the memo
log::debug!("memoized = {}", memoized.get());
});
create_effect(move |_| {
// ✅ reads the current value **without re-running the calculation**
// can be `memoized()` on nightly
let value = memoized.get();
// do something else...
});Implementations§
source§impl<T> Memo<T>
impl<T> Memo<T>
sourcepub fn new(f: impl Fn(Option<&T>) -> T + 'static) -> Memo<T>where
T: PartialEq + 'static,
pub fn new(f: impl Fn(Option<&T>) -> T + 'static) -> Memo<T>where T: PartialEq + 'static,
Creates a new memo from the given function.
This is identical to create_memo.
let value = RwSignal::new(0);
// 🆗 we could create a derived signal with a simple function
let double_value = move || value.get() * 2;
value.set(2);
assert_eq!(double_value(), 4);
// but imagine the computation is really expensive
let expensive = move || really_expensive_computation(value.get()); // lazy: doesn't run until called
Effect::new(move |_| {
// 🆗 run #1: calls `really_expensive_computation` the first time
log::debug!("expensive = {}", expensive());
});
Effect::new(move |_| {
// ❌ run #2: this calls `really_expensive_computation` a second time!
let value = expensive();
// do something else...
});
// instead, we create a memo
// 🆗 run #1: the calculation runs once immediately
let memoized = Memo::new(move |_| really_expensive_computation(value.get()));
Effect::new(move |_| {
// 🆗 reads the current value of the memo
// can be `memoized()` on nightly
log::debug!("memoized = {}", memoized.get());
});
Effect::new(move |_| {
// ✅ reads the current value **without re-running the calculation**
let value = memoized.get();
// do something else...
});Trait Implementations§
source§impl<T> From<Memo<T>> for MaybeSignal<T>
impl<T> From<Memo<T>> for MaybeSignal<T>
source§fn from(value: Memo<T>) -> MaybeSignal<T>
fn from(value: Memo<T>) -> MaybeSignal<T>
Converts to this type from the input type.
source§impl<T> IntoAttribute for Memo<T>where
T: IntoAttribute + Clone,
impl<T> IntoAttribute for Memo<T>where T: IntoAttribute + Clone,
source§impl<T> PartialEq for Memo<T>
impl<T> PartialEq for Memo<T>
source§impl<T> Serialize for Memo<T>where
T: Serialize,
impl<T> Serialize for Memo<T>where T: Serialize,
source§fn serialize<S>(
&self,
serializer: S
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>( &self, serializer: S ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where S: Serializer,
Serialize this value into the given Serde serializer. Read more
source§impl<T> SignalDispose for Memo<T>
impl<T> SignalDispose for Memo<T>
source§impl<T> SignalGet for Memo<T>where
T: Clone,
impl<T> SignalGet for Memo<T>where T: Clone,
Examples
let (count, set_count) = create_signal(0);
let double_count = create_memo(move |_| count.get() * 2);
assert_eq!(double_count.get(), 0);
set_count.set(1);
// can be `double_count()` on nightly
// assert_eq!(double_count(), 2);
assert_eq!(double_count.get(), 2);source§impl<T> SignalGetUntracked for Memo<T>where
T: Clone,
impl<T> SignalGetUntracked for Memo<T>where T: Clone,
source§fn get_untracked(&self) -> T
fn get_untracked(&self) -> T
Gets the signal’s value without creating a dependency on the
current scope. Read more
source§fn try_get_untracked(&self) -> Option<T>
fn try_get_untracked(&self) -> Option<T>
Gets the signal’s value without creating a dependency on the
current scope. Returns [
Some(T)] if the signal is still
valid, None otherwise.source§impl<T> SignalStream<T> for Memo<T>where
T: Clone,
impl<T> SignalStream<T> for Memo<T>where T: Clone,
source§impl<T> SignalWith for Memo<T>
impl<T> SignalWith for Memo<T>
source§impl<T> SignalWithUntracked for Memo<T>
impl<T> SignalWithUntracked for Memo<T>
impl<T> Copy for Memo<T>
impl<T> Eq for Memo<T>
Auto Trait Implementations§
impl<T> RefUnwindSafe for Memo<T>where T: RefUnwindSafe,
impl<T> Send for Memo<T>where T: Send,
impl<T> Sync for Memo<T>where T: Sync,
impl<T> Unpin for Memo<T>where T: Unpin,
impl<T> UnwindSafe for Memo<T>where T: UnwindSafe,
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Checks if this value is equivalent to the given key. Read more
§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
Compare self to
key and return true if they are equal.