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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::borrow::BorrowMut;
use crate::construction::{hook::HookBuilder, types::HookReturn};
use super::{use_ref, Reference};
struct StoredEffect<Args, OnDrop>
where
OnDrop: FnOnce() + 'static,
Args: PartialEq + Clone + 'static,
{
args: Args,
on_drop: Option<OnDrop>,
}
impl<Args, OnDrop> Drop for StoredEffect<Args, OnDrop>
where
OnDrop: FnOnce() + 'static,
Args: PartialEq + Clone + 'static,
{
fn drop(&mut self) {
if let Some(od) = self.on_drop.take() {
od();
}
}
}
pub fn use_effect<Args, OnDrop>(
cc: HookBuilder,
(func, args): (fn(Args) -> OnDrop, Args),
) -> impl HookReturn<()>
where
OnDrop: FnOnce() + 'static,
Args: PartialEq + Clone + 'static,
{
use_effect_relaxed(cc, (func, args))
}
pub fn use_effect_relaxed<Args, OnDrop, Eff>(
cc: HookBuilder,
(func, args): (Eff, Args),
) -> impl HookReturn<()>
where
OnDrop: FnOnce() + 'static,
Args: PartialEq + Clone + 'static,
Eff: FnOnce(Args) -> OnDrop,
{
let cc = cc.init();
let (cc, store): (_, Reference<Option<StoredEffect<Args, OnDrop>>>) = cc.hook(use_ref, ());
let should_run = store
.visit_mut_with(|opt| match opt {
Some(stored) => {
if stored.args != args {
stored.args = args;
true
} else {
false
}
}
opt_none => {
*opt_none = Some(StoredEffect {
args,
on_drop: None,
});
true
}
})
.unwrap();
if should_run {
store
.visit_mut_with(|opt| {
let stored = opt.as_mut().unwrap().borrow_mut();
if let Some(od) = stored.on_drop.take() {
od();
}
stored.on_drop = Some(func(stored.args.clone()));
})
.unwrap();
}
(cc, ())
}