This is unreleased documentation for Yew Next version.
For up-to-date documentation, see the latest version on docs.rs.

yew/functional/hooks/
use_memo.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use std::borrow::Borrow;
use std::rc::Rc;

use super::use_mut_ref;
use crate::functional::hook;

/// Get a immutable reference to a memoized value.
///
/// This version allows for a key cache key derivation that only borrows
/// like the original argument. For example, using ` K = Rc<D>`, we only
/// create a shared reference to dependencies *after* they change.
#[hook]
pub(crate) fn use_memo_base<T, F, D, K>(f: F, deps: D) -> Rc<T>
where
    T: 'static,
    F: FnOnce(D) -> (T, K),
    K: 'static + Borrow<D>,
    D: PartialEq,
{
    struct MemoState<T, K> {
        memo_key: K,
        result: Rc<T>,
    }
    let state = use_mut_ref(|| -> Option<MemoState<T, K>> { None });

    let mut state = state.borrow_mut();
    match &*state {
        Some(existing) if existing.memo_key.borrow() != &deps => {
            // Drop old state if it's outdated
            *state = None;
        }
        _ => {}
    };
    let state = state.get_or_insert_with(|| {
        let (result, memo_key) = f(deps);
        let result = Rc::new(result);
        MemoState { result, memo_key }
    });
    state.result.clone()
}

/// Get a immutable reference to a memoized value.
///
/// Memoization means it will only get recalculated when provided dependencies update/change.
///
/// It can be useful for keeping things in scope for the lifetime of the component,
/// so long as you don't store a clone of the resulting `Rc` anywhere that outlives the component.
///
/// # Example
///
/// ```rust
/// use yew::prelude::*;
///
/// #[derive(PartialEq, Properties)]
/// pub struct Props {
///     pub step: usize,
/// }
///
/// #[function_component(UseMemo)]
/// fn memo(props: &Props) -> Html {
///     // Will only get recalculated if `props.step` value changes
///     let message = use_memo(props.step, |step| {
///         format!("{}. Do Some Expensive Calculation", step)
///     });
///
///     html! {
///         <div>
///             <span>{ (*message).clone() }</span>
///         </div>
///     }
/// }
/// ```
#[hook]
pub fn use_memo<T, F, D>(deps: D, f: F) -> Rc<T>
where
    T: 'static,
    F: FnOnce(&D) -> T,
    D: 'static + PartialEq,
{
    use_memo_base(|d| (f(&d), d), deps)
}