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