leptos/await_.rs
1use crate::{prelude::Suspend, suspense_component::Suspense, IntoView};
2use leptos_macro::{component, view};
3use leptos_server::ArcOnceResource;
4use reactive_graph::prelude::ReadUntracked;
5use serde::{de::DeserializeOwned, Serialize};
6
7#[component]
8/// Allows you to inline the data loading for an `async` block or
9/// server function directly into your view. This is the equivalent of combining a
10/// [`create_resource`] that only loads once (i.e., with a source signal `|| ()`) with
11/// a [`Suspense`] with no `fallback`.
12///
13/// Adding `let:{variable name}` to the props makes the data available in the children
14/// that variable name, when resolved.
15/// ```
16/// # use leptos::prelude::*;
17/// # if false {
18/// async fn fetch_monkeys(monkey: i32) -> i32 {
19/// // do some expensive work
20/// 3
21/// }
22///
23/// view! {
24/// <Await
25/// future=fetch_monkeys(3)
26/// let:data
27/// >
28/// <p>{*data} " little monkeys, jumping on the bed."</p>
29/// </Await>
30/// }
31/// # ;
32/// # }
33/// ```
34pub fn Await<T, Fut, Chil, V>(
35 /// A [`Future`](std::future::Future) that will the component will `.await`
36 /// before rendering.
37 future: Fut,
38 /// If `true`, the component will create a blocking resource, preventing
39 /// the HTML stream from returning anything before `future` has resolved.
40 #[prop(optional)]
41 blocking: bool,
42 /// A function that takes a reference to the resolved data from the `future`
43 /// renders a view.
44 ///
45 /// ## Syntax
46 /// This can be passed in the `view` children of the `<Await/>` by using the
47 /// `let:` syntax to specify the name for the data variable.
48 ///
49 /// ```rust
50 /// # use leptos::prelude::*;
51 /// # if false {
52 /// # async fn fetch_monkeys(monkey: i32) -> i32 {
53 /// # 3
54 /// # }
55 /// view! {
56 /// <Await
57 /// future=fetch_monkeys(3)
58 /// let:data
59 /// >
60 /// <p>{*data} " little monkeys, jumping on the bed."</p>
61 /// </Await>
62 /// }
63 /// # ;
64 /// # }
65 /// ```
66 /// is the same as
67 /// ```rust
68 /// # use leptos::prelude::*;
69 /// # if false {
70 /// # async fn fetch_monkeys(monkey: i32) -> i32 {
71 /// # 3
72 /// # }
73 /// view! {
74 /// <Await
75 /// future=fetch_monkeys(3)
76 /// children=|data| view! {
77 /// <p>{*data} " little monkeys, jumping on the bed."</p>
78 /// }
79 /// />
80 /// }
81 /// # ;
82 /// # }
83 /// ```
84 children: Chil,
85) -> impl IntoView
86where
87 T: Send + Sync + Serialize + DeserializeOwned + 'static,
88 Fut: std::future::Future<Output = T> + Send + 'static,
89 Chil: FnOnce(&T) -> V + Send + 'static,
90 V: IntoView + 'static,
91{
92 let res = ArcOnceResource::<T>::new_with_options(future, blocking);
93 let ready = res.ready();
94
95 view! {
96 <Suspense fallback=|| ()>
97 {Suspend::new(async move {
98 ready.await;
99 children(res.read_untracked().as_ref().unwrap())
100 })}
101
102 </Suspense>
103 }
104}