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 if future.as_mut().poll(cx).is_ready() {
38 self.f = None;
39 }
40 }
41 Poll::Pending
42 }
43}
44
45impl UseEffect for crate::Hooks<'_, '_> {
46 fn use_effect<F, D>(&mut self, f: F, deps: D)
47 where
48 F: FnOnce(),
49 D: Hash,
50 {
51 self.use_memo(f, deps)
52 }
53
54 fn use_async_effect<F, D>(&mut self, f: F, deps: D)
55 where
56 F: Future<Output = ()> + Send + 'static,
57 D: Hash,
58 {
59 let dep_hash = hash_deps(deps);
60 let hook = self.use_hook(UseAsyncEffectImpl::default);
61
62 if hook.deps_hash != dep_hash {
63 hook.f = Some(f.boxed());
64 hook.deps_hash = dep_hash;
65 }
66 }
67}