rosace_core/lifecycle.rs
1use crate::context::Context;
2
3/// Runs `f` exactly once when the component first mounts, and registers the
4/// returned cleanup function to run exactly once when the component unmounts.
5///
6/// This is idempotent: if `build()` is called multiple times (once per frame),
7/// the setup runs only on the first call thanks to persistent hook state.
8pub fn on_mount<F, Cleanup>(ctx: &mut Context, f: F)
9where
10 F: FnOnce() -> Cleanup + Send + 'static,
11 Cleanup: FnOnce() + Send + 'static,
12{
13 let already_mounted = ctx.state(false);
14 if !already_mounted.get() {
15 already_mounted.set(true);
16 let cleanup = f();
17 ctx.on_cleanup(cleanup);
18 }
19}
20
21/// Registers `f` to run exactly once when the component unmounts.
22///
23/// Idempotent: repeated calls from the same hook slot (across frames) register
24/// the cleanup only on first call.
25pub fn on_unmount(ctx: &mut Context, f: impl FnOnce() + Send + 'static) {
26 let already_registered = ctx.state(false);
27 if !already_registered.get() {
28 already_registered.set(true);
29 ctx.on_cleanup(f);
30 }
31}