ratatui_kit/hooks/
use_async_state.rs1use std::future::Future;
2
3use crate::{Hooks, State, UseEffect, UseState};
4
5mod private {
6 pub trait Sealed {}
7 impl Sealed for crate::Hooks<'_, '_> {}
8}
9
10pub struct AsyncState<T, E>
12where
13 T: Unpin + Send + Sync + 'static,
14 E: Unpin + Send + Sync + 'static,
15{
16 pub data: State<Option<T>>,
17 pub loading: State<bool>,
18 pub error: State<Option<E>>,
19}
20
21pub trait UseAsyncState: private::Sealed {
22 fn use_async_state<F, Fut, D, T, E>(&mut self, f: F, deps: D) -> AsyncState<T, E>
24 where
25 F: FnOnce() -> Fut + 'static,
26 Fut: Future<Output = Result<T, E>> + 'static,
27 D: PartialEq + Unpin + 'static,
28 T: Unpin + Send + Sync + 'static,
29 E: Unpin + Send + Sync + 'static;
30}
31
32impl UseAsyncState for Hooks<'_, '_> {
33 fn use_async_state<F, Fut, D, T, E>(&mut self, f: F, deps: D) -> AsyncState<T, E>
34 where
35 F: FnOnce() -> Fut + 'static,
36 Fut: Future<Output = Result<T, E>> + 'static,
37 D: PartialEq + Unpin + 'static,
38 T: Unpin + Send + Sync + 'static,
39 E: Unpin + Send + Sync + 'static,
40 {
41 let mut data = self.use_state(|| None::<T>);
42 let mut loading = self.use_state(|| false);
43 let mut error = self.use_state(|| None::<E>);
44
45 self.use_async_effect(
46 async move {
47 loading.set(true);
48 error.set(None);
49
50 match f().await {
51 Ok(value) => {
52 data.set(Some(value));
53 }
54 Err(err) => {
55 error.set(Some(err));
56 }
57 }
58
59 loading.set(false);
60 },
61 deps,
62 );
63
64 AsyncState {
65 data,
66 loading,
67 error,
68 }
69 }
70}