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
use std::{any::Any, cell::RefCell, rc::Rc};
use super::IntoRc;
pub fn use_memo_no_dep<T: Any, R: IntoRc<T>, F: FnOnce() -> R>(func: F) -> Rc<T> {
let mut func = super::utils::fn_once_in_runtime(move || {
let rc = func().into_rc();
let k = forgotten::forget_rc(rc).into_shared();
let k = k.as_usize();
*k
});
let obj = react_sys::use_ref_usize_with(&mut func);
let k = obj.current();
let v = forgotten::try_get(&unsafe { forgotten::SharedForgottenKey::<T>::from_usize(k) })
.expect("use memo ptr should not be freed before element unmounted");
super::use_effect_on_mounted(move || {
move || {
unsafe { forgotten::try_free_with_usize(k) };
}
});
v
}
pub fn use_memo_one<
D: 'static + PartialEq,
T: 'static,
RD: IntoRc<D>,
RT: IntoRc<T>,
F: FnOnce(&Rc<D>) -> RT,
>(
func: F,
dep: RD,
) -> Rc<T> {
let dep: Rc<D> = dep.into_rc();
let dep_and_value =
use_memo_no_dep::<RefCell<Option<(Rc<D>, Rc<T>)>>, _, _>(|| RefCell::new(None));
let mut dep_and_value = dep_and_value.as_ref().borrow_mut();
match &*dep_and_value {
Some(t) if &t.0 == &dep => {
Rc::clone(&t.1)
}
_ => {
let new_v: Rc<T> = func(&dep).into_rc();
*dep_and_value = Some((dep, new_v.clone()));
new_v
}
}
}
#[macro_export]
macro_rules! use_memo {
( <$t:ty> $(move)? || $e:expr ) => {
$crate::react::use_memo_no_dep::<$t, _, _>($(move)? || $e)
};
( <$t:ty> $(move)? | $($dep:ident),+ $(,)? | $e:expr ) => {
$crate::react::use_memo_one::<_, $t, _, _>($(move)? |($($dep:ident),+)| $e , ($($dep:ident),+))
};
( $(move)? || $e:expr ) => {
$crate::react::use_memo_no_dep(|| $e)
};
( $(move)? | $($dep:ident),+ $(,)? | $e:expr ) => {
$crate::react::use_memo_one($(move)? |($($dep:ident),+)| $e , ($($dep:ident),+))
};
}