1use std::hash::{DefaultHasher, Hash, Hasher};
2
3use async_context::with_async_context_mut;
4
5use crate::hook::Hook;
6
7pub struct Cleanup(Box<dyn FnOnce()>);
8
9impl From<()> for Cleanup {
10 fn from(_: ()) -> Self {
11 Self(Box::new(|| {}))
12 }
13}
14
15impl<C> From<C> for Cleanup
16where
17 C: FnOnce() + 'static,
18{
19 fn from(cleanup: C) -> Self {
20 Self(Box::new(cleanup))
21 }
22}
23
24impl Cleanup {
25 pub(crate) fn run(self) {
26 let cleanup = self.0;
27 cleanup()
28 }
29}
30
31pub(crate) struct Effect(Box<dyn FnOnce() -> Cleanup + Send + Sync + 'static>);
32
33impl Effect {
34 pub(crate) fn run(self) -> Cleanup {
35 let effect = self.0;
36 effect()
37 }
38}
39
40pub fn use_effect<A, C>(arg: A, effect: fn(A) -> C)
41where
42 A: Hash + Send + Sync + 'static,
43 C: Into<Cleanup> + 'static,
44{
45 with_async_context_mut(|hook: Option<&mut Hook>| {
46 if let Some(hook) = hook {
47 let mut hasher = DefaultHasher::new();
48 arg.hash(&mut hasher);
49 let arg_hash = hasher.finish();
50
51 hook.effects
52 .push((arg_hash, Effect(Box::new(move || effect(arg).into()))));
53 }
54 })
55}