ratatui_kit/hooks/
use_effect.rs1use 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}