dioxus_hooks/
use_effect.rs1use std::{cell::Cell, rc::Rc};
2
3use dioxus_core::*;
4use futures_util::StreamExt;
5
6use crate::use_callback;
7
8#[doc = include_str!("../docs/side_effects.md")]
9#[doc = include_str!("../docs/rules_of_hooks.md")]
10#[track_caller]
11pub fn use_effect(mut callback: impl FnMut() + 'static) -> Effect {
12    let callback = use_callback(move |_| callback());
13
14    let location = std::panic::Location::caller();
15
16    use_hook(|| {
17        let (rc, mut changed) = ReactiveContext::new_with_origin(location);
19
20        let effect_queued = Rc::new(Cell::new(false));
22
23        let queue_effect_for_next_render = move || {
28            if effect_queued.get() {
29                return;
30            }
31            effect_queued.set(true);
32            let effect_queued = effect_queued.clone();
33            queue_effect(move || {
34                rc.reset_and_run_in(|| callback(()));
35                effect_queued.set(false);
36            });
37        };
38
39        queue_effect_for_next_render();
40        spawn(async move {
41            loop {
42                let _ = changed.next().await;
44
45                queue_effect_for_next_render();
47            }
48        });
49        Effect { rc }
50    })
51}
52
53#[derive(Clone, Copy)]
55pub struct Effect {
56    rc: ReactiveContext,
57}
58
59impl Effect {
60    pub fn mark_dirty(&mut self) {
62        self.rc.mark_dirty();
63    }
64}