ratatui_kit/hooks/
use_effect.rs

1use futures::{FutureExt, future::BoxFuture};
2use std::{hash::Hash, task::Poll};
3
4use crate::{Hook, UseMemo, hash_deps};
5
6mod private {
7    pub trait Sealed {}
8    impl Sealed for crate::Hooks<'_, '_> {}
9}
10
11pub trait UseEffect: private::Sealed {
12    fn use_effect<F, D>(&mut self, f: F, deps: D)
13    where
14        F: FnOnce(),
15        D: Hash;
16
17    fn use_async_effect<F, D>(&mut self, f: F, deps: D)
18    where
19        F: Future<Output = ()> + Send + 'static,
20        D: Hash;
21}
22
23#[derive(Default)]
24pub struct UseAsyncEffectImpl {
25    f: Option<BoxFuture<'static, ()>>,
26    deps_hash: u64,
27}
28
29impl Hook for UseAsyncEffectImpl {
30    fn poll_change(
31        mut self: std::pin::Pin<&mut Self>,
32        cx: &mut std::task::Context,
33    ) -> std::task::Poll<()> {
34        if let Some(future) = self.f.as_mut() {
35            if future.as_mut().poll(cx).is_ready() {
36                self.f = None;
37            }
38        }
39        Poll::Pending
40    }
41}
42
43impl UseEffect for crate::Hooks<'_, '_> {
44    fn use_effect<F, D>(&mut self, f: F, deps: D)
45    where
46        F: FnOnce(),
47        D: Hash,
48    {
49        self.use_memo(f, deps)
50    }
51
52    fn use_async_effect<F, D>(&mut self, f: F, deps: D)
53    where
54        F: Future<Output = ()> + Send + 'static,
55        D: Hash,
56    {
57        let dep_hash = hash_deps(deps);
58        let hook = self.use_hook(UseAsyncEffectImpl::default);
59
60        if hook.deps_hash != dep_hash {
61            hook.f = Some(f.boxed());
62            hook.deps_hash = dep_hash;
63        }
64    }
65}