repose_core/
effects_ext.rs1use crate::{Dispose, on_unmount, remember, scoped_effect};
2use std::cell::RefCell;
3
4pub fn disposable_effect<K: PartialEq + Clone + 'static>(
6 key: K,
7 effect: impl FnOnce() -> Dispose + 'static,
8) {
9 let last_key = remember(|| RefCell::new(None::<K>));
11 let cleanup_slot = remember(|| RefCell::new(None::<Dispose>));
12 let installed = remember(|| RefCell::new(false));
13
14 if !*installed.borrow() {
16 *installed.borrow_mut() = true;
17 let cleanup_slot = cleanup_slot.clone();
18 scoped_effect(move || {
19 on_unmount(move || {
20 if let Some(d) = cleanup_slot.borrow_mut().take() {
21 d.run();
22 }
23 })
24 });
25 }
26
27 let changed = last_key.borrow().as_ref() != Some(&key);
29 if changed {
30 *last_key.borrow_mut() = Some(key);
31
32 if let Some(d) = cleanup_slot.borrow_mut().take() {
33 d.run();
34 }
35
36 let d = effect();
37 *cleanup_slot.borrow_mut() = Some(d);
38 }
39}
40
41pub fn side_effect(effect: impl Fn()) {
43 effect();
44}
45
46pub fn launched_effect_internal<K: PartialEq + Clone + 'static>(
48 callsite: &'static str,
49 key: K,
50 effect: impl FnOnce() + 'static,
51) {
52 let last_key =
54 crate::remember_with_key(format!("launched:{callsite}"), || RefCell::new(None::<K>));
55
56 let mut last = last_key.borrow_mut();
57 if last.as_ref() != Some(&key) {
58 *last = Some(key);
59 effect();
61 }
62}
63
64#[macro_export] macro_rules! launched_effect {
66 ($key:expr, $effect:expr) => {
67 $crate::effects_ext::launched_effect_internal(
68 concat!(module_path!(), ":", line!(), ":", column!()),
69 $key,
70 $effect,
71 )
72 };
73}