hooks/state_with_updater/update_state/
set.rs

1#[cfg(feature = "use_shared_set")]
2pub use shared::*;
3
4#[cfg(feature = "use_gen_set")]
5pub use gen::*;
6
7use super::UpdateState;
8
9#[derive(Debug)]
10pub struct Set<T> {
11    pub new_value: Option<T>,
12}
13
14impl<S> Set<S> {
15    pub fn set(&mut self, new_value: S) {
16        self.new_value = Some(new_value)
17    }
18}
19
20impl<T> Default for Set<T> {
21    fn default() -> Self {
22        Self { new_value: None }
23    }
24}
25
26impl<T> UpdateState<T> for Set<T> {
27    fn update_state(&mut self, state: &mut T) -> bool {
28        if let Some(this) = self.new_value.take() {
29            *state = this;
30            true
31        } else {
32            false
33        }
34    }
35}
36
37#[cfg(feature = "use_shared_set")]
38mod shared {
39    use super::{
40        super::{
41            use_shared_update_state, use_shared_update_state_with, SharedUpdateState,
42            UseSharedUpdateState, UseSharedUpdateStateWith,
43        },
44        Set,
45    };
46
47    pub type SharedSet<S> = SharedUpdateState<Set<S>>;
48
49    impl<S> SharedSet<S> {
50        pub fn set(&self, new_value: S) {
51            self.map_mut_update_state(|v| v.set(new_value))
52        }
53    }
54
55    pub type UseSharedSet<S> = UseSharedUpdateState<S, Set<S>>;
56    pub fn use_shared_set<S>(initial_state: S) -> UseSharedSet<S> {
57        use_shared_update_state(initial_state, Set::default())
58    }
59
60    pub type UseSharedSetWith<S, F> = UseSharedUpdateStateWith<S, Set<S>, F>;
61    pub fn use_shared_set_with<S>(
62        get_initial_state: impl FnOnce() -> S,
63    ) -> UseSharedSetWith<S, impl FnOnce() -> (S, SharedSet<S>)> {
64        use_shared_update_state_with(move || (get_initial_state(), Set::default()))
65    }
66
67    #[cfg(test)]
68    mod tests {
69        use crate::{Hook, HookPollNextUpdateExt, IntoHook};
70
71        #[test]
72        fn set() {
73            futures_lite::future::block_on(async {
74                let hook = super::use_shared_set(1).into_hook();
75                futures_lite::pin!(hook);
76
77                assert!(!std::future::poll_fn(|cx| hook.poll_next_update(cx)).await);
78
79                let (state, updater) = hook.as_mut().use_hook();
80                assert_eq!(*state, 1);
81                updater.set(2);
82                assert_eq!(*state, 1);
83
84                assert!(std::future::poll_fn(|cx| hook.poll_next_update(cx)).await);
85                let (state, _updater) = hook.as_mut().use_hook();
86                assert_eq!(*state, 2);
87
88                assert!(!std::future::poll_fn(|cx| hook.poll_next_update(cx)).await);
89            });
90        }
91
92        #[cfg(feature = "futures-core")]
93        #[cfg(feature = "use_effect")]
94        #[test]
95        fn hook_fn_state_2() {
96            use futures_lite::StreamExt;
97            use hooks_core::{hook_fn, IntoHook};
98
99            use crate::{use_shared_set, use_shared_set_with};
100
101            hook_fn!(
102                fn use_state_2() -> (i32, i32) {
103                    let (state_1, updater_1) = h!(use_shared_set(1));
104                    let (state_2, updater_2) = h!(use_shared_set_with(|| *state_1 + 1));
105
106                    let ret = (*state_1, *state_2);
107
108                    let updater_1 = updater_1.clone();
109                    let updater_2 = updater_2.clone();
110                    h![crate::use_effect(
111                        move |(v1, v2): &_| {
112                            if *v2 > 10 {
113                                return;
114                            }
115                            updater_1.set(*v2);
116                            updater_2.set(*v1 + *v2);
117                        },
118                        ret,
119                    )];
120
121                    ret
122                }
123            );
124
125            futures_lite::future::block_on(async {
126                let values = use_state_2().into_hook_values().collect::<Vec<_>>().await;
127
128                assert_eq!(values, [(1, 2), (2, 3), (3, 5), (5, 8), (8, 13)]);
129            });
130        }
131
132        #[cfg(feature = "futures-core")]
133        #[cfg(feature = "use_effect")]
134        #[cfg(feature = "proc-macro")]
135        #[test]
136        fn state_2() {
137            use futures_lite::StreamExt;
138            use hooks_core::IntoHook;
139            use hooks_macro::hook;
140
141            use super::{use_shared_set, use_shared_set_with};
142
143            #[hook(hooks_core_path = "::hooks_core")]
144            fn use_state_2() -> (i32, i32) {
145                let (state_1, updater_1) = use_shared_set(1);
146                let (state_2, updater_2) = use_shared_set_with(|| *state_1 + 1);
147
148                let ret = (*state_1, *state_2);
149
150                let updater_1 = updater_1.clone();
151                let updater_2 = updater_2.clone();
152                crate::use_effect(
153                    move |(v1, v2): &_| {
154                        if *v2 > 10 {
155                            return;
156                        }
157                        updater_1.set(*v2);
158                        updater_2.set(*v1 + *v2);
159                    },
160                    ret,
161                );
162
163                ret
164            }
165
166            futures_lite::future::block_on(async {
167                let values = use_state_2().into_hook_values().collect::<Vec<_>>().await;
168
169                assert_eq!(values, [(1, 2), (2, 3), (3, 5), (5, 8), (8, 13)]);
170            });
171        }
172    }
173}
174
175#[cfg(feature = "use_gen_set")]
176mod gen {
177    use super::{
178        super::{
179            use_gen_update_state, use_gen_update_state_with, GenUpdateStateKey,
180            GenUpdateStateOwner, UseGenUpdateState, UseGenUpdateStateWith,
181        },
182        Set,
183    };
184
185    pub type GenSetOwner<S> = GenUpdateStateOwner<Set<S>>;
186    pub type GenSetKey<S> = GenUpdateStateKey<Set<S>>;
187
188    impl<S> GenSetKey<S> {
189        pub fn set(&self, new_value: S) {
190            self.map_mut_update_state(|v| v.set(new_value))
191        }
192    }
193
194    pub type UseGenSet<S> = UseGenUpdateState<S, Set<S>>;
195    pub fn use_gen_set<S>(initial_state: S) -> UseGenSet<S> {
196        use_gen_update_state(initial_state, Set::default())
197    }
198
199    pub type UseGenSetWith<F> = UseGenUpdateStateWith<F>;
200    pub fn use_gen_set_with<S>(
201        get_initial_state: impl FnOnce() -> S,
202    ) -> UseGenSetWith<impl FnOnce() -> (S, Set<S>)> {
203        use_gen_update_state_with(move || (get_initial_state(), Set::default()))
204    }
205
206    #[cfg(test)]
207    mod tests {
208        use crate::{utils::testing::assert_always_pending, Hook, HookPollNextUpdateExt, IntoHook};
209
210        #[test]
211        fn set() {
212            futures_lite::future::block_on(async {
213                let hook = super::use_gen_set(1).into_hook();
214                futures_lite::pin!(hook);
215
216                assert_always_pending(|| std::future::poll_fn(|cx| hook.poll_next_update(cx)));
217
218                let (state, updater) = hook.as_mut().use_hook();
219                assert_eq!(*state, 1);
220                updater.set(2);
221                assert_eq!(*state, 1);
222
223                assert!(std::future::poll_fn(|cx| hook.poll_next_update(cx)).await);
224                let (state, _updater) = hook.as_mut().use_hook();
225                assert_eq!(*state, 2);
226
227                assert_always_pending(|| std::future::poll_fn(|cx| hook.poll_next_update(cx)));
228            });
229        }
230
231        #[cfg(feature = "futures-core")]
232        #[cfg(feature = "use_effect")]
233        #[test]
234        fn hook_fn_state_2() {
235            use futures_lite::StreamExt;
236            use hooks_core::{hook_fn, IntoHook};
237
238            use super::{use_gen_set, use_gen_set_with};
239
240            hook_fn!(
241                fn use_state_2() -> (i32, i32) {
242                    let (state_1, updater_1) = h!(use_gen_set(1));
243                    let (state_2, updater_2) = h!(use_gen_set_with(|| *state_1 + 1));
244
245                    let ret = (*state_1, *state_2);
246
247                    h![crate::use_effect(
248                        move |(v1, v2): &_| {
249                            if *v2 > 10 {
250                                return;
251                            }
252                            updater_1.set(*v2);
253                            updater_2.set(*v1 + *v2);
254                        },
255                        ret,
256                    )];
257
258                    ret
259                }
260            );
261
262            futures_lite::future::block_on(async {
263                let mut hook_values = use_state_2().into_hook_values();
264                let values = (&mut hook_values).take(5).collect::<Vec<_>>().await;
265
266                assert_eq!(values, [(1, 2), (2, 3), (3, 5), (5, 8), (8, 13)]);
267
268                assert_always_pending(|| hook_values.next())
269            });
270        }
271
272        #[cfg(feature = "futures-core")]
273        #[cfg(feature = "use_effect")]
274        #[cfg(feature = "proc-macro")]
275        #[test]
276        fn state_2() {
277            use futures_lite::StreamExt;
278            use hooks_core::IntoHook;
279            use hooks_macro::hook;
280
281            use super::{use_gen_set, use_gen_set_with};
282
283            #[hook(hooks_core_path = "::hooks_core")]
284            fn use_state_2() -> (i32, i32) {
285                let (state_1, updater_1) = use_gen_set(1);
286                let (state_2, updater_2) = use_gen_set_with(|| *state_1 + 1);
287
288                let ret = (*state_1, *state_2);
289
290                crate::use_effect(
291                    move |(v1, v2): &_| {
292                        if *v2 > 10 {
293                            return;
294                        }
295                        updater_1.set(*v2);
296                        updater_2.set(*v1 + *v2);
297                    },
298                    ret,
299                );
300
301                ret
302            }
303
304            futures_lite::future::block_on(async {
305                let mut hook_values = use_state_2().into_hook_values();
306                let values = (&mut hook_values).take(5).collect::<Vec<_>>().await;
307
308                assert_eq!(values, [(1, 2), (2, 3), (3, 5), (5, 8), (8, 13)]);
309
310                assert_always_pending(|| hook_values.next())
311            });
312        }
313    }
314}