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 crate::{
construction::{hook::HookBuilder, types::HookReturn},
executor::RerenderTask,
locking::SubtreeUnmountedError,
};
use super::use_ref::{use_ref, Reference};
#[derive(Clone, PartialEq)]
pub struct Updater<T: 'static> {
state: Reference<Option<T>>,
rerender_task: RerenderTask,
}
impl<T> Updater<T> {
pub fn update_with<F: FnOnce(T) -> T>(&self, func: F) {
self.try_update_with(func).ok();
}
pub fn try_update_with<F: FnOnce(T) -> T>(&self, func: F) -> Result<(), SubtreeUnmountedError> {
self.state
.visit_mut_with(|state| *state = Some(func(state.take().unwrap())))?;
self.rerender_task.clone().enqueue();
Ok(())
}
pub fn set_to(&self, value: T) {
self.try_set_to(value).ok();
}
pub fn try_set_to(&self, value: T) -> Result<(), SubtreeUnmountedError> {
self.state.visit_mut_with(|state| *state = Some(value))?;
self.rerender_task.clone().enqueue();
Ok(())
}
}
pub fn use_state_from<T, F>(cc: HookBuilder, default_from: F) -> impl HookReturn<(T, Updater<T>)>
where
T: Clone + 'static,
F: FnOnce() -> T,
{
let cc = cc.init();
let (cc, state): (_, Reference<Option<T>>) = cc.hook(use_ref::<Option<T>>, ());
let value = state
.visit_mut_with(|opt| opt.get_or_insert_with(default_from).clone())
.unwrap();
let setter = Updater {
state,
rerender_task: RerenderTask::new(cc.current_component, cc.lock.clone()),
};
(cc, (value, setter))
}
pub fn use_state<T>(cc: HookBuilder, default_value: T) -> impl HookReturn<(T, Updater<T>)>
where
T: Copy + Clone + 'static,
{
use_state_from(cc, move || default_value)
}