repose_core/
effects.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3
4#[derive(Clone)]
5pub struct Dispose(Rc<RefCell<Option<Box<dyn FnOnce()>>>>);
6
7impl Dispose {
8    pub fn new(f: impl FnOnce() + 'static) -> Self {
9        Self(Rc::new(RefCell::new(Some(Box::new(f)))))
10    }
11
12    /// Runs at most once (safe to call multiple times).
13    pub fn run(&self) {
14        if let Some(f) = self.0.borrow_mut().take() {
15            f()
16        }
17    }
18}
19
20/// Runs `f()` immediately and returns its `Dispose`.
21pub fn effect<F>(f: F) -> Dispose
22where
23    F: FnOnce() -> Dispose + 'static,
24{
25    // run now
26    let d = f();
27
28    // auto-register cleanup in the current scope if one exists
29    if let Some(scope) = crate::scope::current_scope() {
30        let d2 = d.clone();
31        scope.add_disposer(move || d2.run());
32    }
33
34    d
35}
36/// Helper to register cleanup inside effect.
37pub fn on_unmount(f: impl FnOnce() + 'static) -> Dispose {
38    Dispose::new(f)
39}