repose_core/
effects_ext.rs

1use crate::{remember_with_key, scoped_effect};
2use std::cell::RefCell;
3
4/// cleanup on key change or unmount
5pub fn disposable_effect<K: PartialEq + Clone + 'static>(
6    _key: K,
7    effect: impl FnOnce() -> Box<dyn FnOnce()> + 'static,
8) {
9    scoped_effect(|| {
10        let cleanup = effect();
11        cleanup
12    });
13}
14
15/// runs on every recomposition
16pub fn side_effect(effect: impl Fn()) {
17    effect();
18}
19
20/// Internal implementation: keyed by a per-callsite id string.
21pub fn launched_effect_internal<K: PartialEq + Clone + 'static>(
22    callsite: &'static str,
23    key: K,
24    effect: impl FnOnce() + 'static,
25) {
26    // One slot per call-site, with K baked into its type.
27    let last_key = remember_with_key(format!("launched:{callsite}"), || RefCell::new(None::<K>));
28
29    let mut last = last_key.borrow_mut();
30    if last.as_ref() != Some(&key) {
31        *last = Some(key);
32        // doesn't cancel on unmount
33        effect();
34    }
35}
36
37#[macro_export] // Should probably move this to macros (might want to move the above  part too?)
38macro_rules! launched_effect {
39    ($key:expr, $effect:expr) => {
40        $crate::effects_ext::launched_effect_internal(
41            concat!(module_path!(), ":", line!(), ":", column!()),
42            $key,
43            $effect,
44        )
45    };
46}