Skip to main content

ratatui_kit/hooks/
use_async_state.rs

1use 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
10// 异步数据加载的三态结果。
11pub 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    // 依赖变化时运行异步任务,并维护 data/loading/error 三态。
23    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}