freya_core/lifecycle/
effect.rs1use std::{
2 cell::RefCell,
3 rc::Rc,
4};
5
6use crate::{
7 prelude::{
8 State,
9 spawn,
10 use_hook,
11 use_reactive,
12 },
13 reactive_context::ReactiveContext,
14};
15
16pub struct Effect;
17
18impl Effect {
19 pub fn create(mut callback: impl FnMut() + 'static) {
20 let (rx, rc) = ReactiveContext::new_for_task();
21 spawn(async move {
22 loop {
23 ReactiveContext::run(rc.clone(), &mut callback);
24 rx.notified().await;
25 }
26 });
27 }
28
29 pub fn create_with_gen(mut callback: impl FnMut(usize) + 'static) {
30 let (rx, rc) = ReactiveContext::new_for_task();
31 spawn(async move {
32 let mut current_gen = 0;
33 loop {
34 ReactiveContext::run(rc.clone(), || callback(current_gen));
35 rx.notified().await;
36 current_gen += 1;
37 }
38 });
39 }
40
41 pub fn create_sync(mut callback: impl FnMut() + 'static) {
42 let (rx, rc) = ReactiveContext::new_for_task();
43 ReactiveContext::run(rc.clone(), &mut callback);
44 spawn(async move {
45 loop {
46 rx.notified().await;
47 ReactiveContext::run(rc.clone(), &mut callback);
48 }
49 });
50 }
51
52 pub fn create_after(callback: impl FnMut() + 'static) {
53 let (rx, rc) = ReactiveContext::new_for_task();
54 let callback = Rc::new(RefCell::new(callback));
55 spawn(async move {
56 loop {
57 let callback = callback.clone();
58 let rc = rc.clone();
59 spawn(async move {
60 ReactiveContext::run(rc, &mut *callback.borrow_mut());
61 });
62 rx.notified().await;
63 }
64 });
65 }
66
67 pub fn create_value<T: 'static>(mut callback: impl FnMut() -> T + 'static) -> State<T> {
68 let (rx, rc) = ReactiveContext::new_for_task();
69 let mut state = State::create(ReactiveContext::run(rc.clone(), &mut callback));
70 spawn(async move {
71 let mut current_gen = 0;
72 loop {
73 if current_gen > 0 {
74 state.set(ReactiveContext::run(rc.clone(), &mut callback));
75 }
76 rx.notified().await;
77 current_gen += 1;
78 }
79 });
80 state
81 }
82}
83
84pub fn use_side_effect(callback: impl FnMut() + 'static) {
86 use_hook(|| Effect::create(callback));
87}
88
89pub fn use_after_side_effect(callback: impl FnMut() + 'static) {
90 use_hook(|| Effect::create_after(callback));
91}
92
93pub fn use_side_effect_value<T: 'static>(callback: impl FnMut() -> T + 'static) -> State<T> {
94 use_hook(|| Effect::create_value(callback))
95}
96
97pub fn use_side_effect_with_deps<D: 'static + Clone + PartialEq>(
98 deps: &D,
99 mut callback: impl FnMut(&D) + 'static,
100) {
101 let deps = use_reactive(deps);
102 use_hook(move || {
103 Effect::create(move || {
104 let deps = deps.read();
105 callback(&deps)
106 })
107 });
108}