This is unreleased documentation for Yew Next version.
For up-to-date documentation, see the latest version on docs.rs.

yew/functional/hooks/use_prepared_state/
mod.rs

1#[cfg(feature = "hydration")]
2pub(super) mod feat_hydration;
3#[cfg(all(feature = "hydration", feature = "ssr"))]
4mod feat_hydration_ssr;
5#[cfg(not(any(feature = "hydration", feature = "ssr")))]
6pub(super) mod feat_none;
7#[cfg(feature = "ssr")]
8mod feat_ssr;
9
10#[cfg(all(feature = "hydration", not(feature = "ssr")))]
11pub use feat_hydration::*;
12#[cfg(all(feature = "ssr", feature = "hydration"))]
13pub use feat_hydration_ssr::*;
14#[cfg(not(any(feature = "hydration", feature = "ssr")))]
15pub use feat_none::*;
16#[cfg(all(feature = "ssr", not(feature = "hydration")))]
17pub use feat_ssr::*;
18/// Use a state prepared on the server side and its value is sent to the client side during
19/// hydration.
20///
21/// The component sees the same value on the server side and client side if the component is
22/// hydrated.
23///
24/// It accepts a closure as the first argument and a dependency type as the second argument.
25/// It returns `SuspensionResult<Option<Rc<T>>>`.
26///
27/// During hydration, it will only return `Ok(Some(Rc<T>))` if the component is hydrated from a
28/// server-side rendering artifact and its dependency value matches.
29///
30/// `let state = use_prepared_state!(|deps| -> ReturnType { ... }, deps)?;`
31///
32/// It has the following signature:
33///
34/// ```
35/// # use serde::de::DeserializeOwned;
36/// # use serde::Serialize;
37/// # use std::rc::Rc;
38/// use yew::prelude::*;
39/// use yew::suspense::SuspensionResult;
40///
41/// #[hook]
42/// pub fn use_prepared_state<T, D, F>(deps: D, f: F) -> SuspensionResult<Option<Rc<T>>>
43/// where
44///     D: Serialize + DeserializeOwned + PartialEq + 'static,
45///     T: Serialize + DeserializeOwned + 'static,
46///     F: FnOnce(Rc<D>) -> T,
47/// # { todo!() }
48/// ```
49///
50/// The first argument can also be an [async closure](https://github.com/rust-lang/rust/issues/62290).
51///
52/// `let state = use_prepared_state!(async |deps| -> ReturnType { ... }, deps)?;`
53///
54/// When accepting an async closure, it has the following signature:
55///
56/// ```
57/// # use serde::de::DeserializeOwned;
58/// # use serde::Serialize;
59/// # use std::rc::Rc;
60/// # use std::future::Future;
61/// use yew::prelude::*;
62/// use yew::suspense::SuspensionResult;
63///
64/// #[hook]
65/// pub fn use_prepared_state<T, D, F, U>(
66///         deps: D,
67///         f: F,
68///     ) -> SuspensionResult<Option<Rc<T>>>
69///     where
70///         D: Serialize + DeserializeOwned + PartialEq + 'static,
71///         T: Serialize + DeserializeOwned + 'static,
72///         F: FnOnce(Rc<D>) -> U,
73///         U: 'static + Future<Output = T>,
74/// # { todo!() }
75/// ```
76///
77/// During server-side rendering, a value of type `T` will be calculated from the first
78/// closure.
79///
80/// If the bundle is compiled without server-side rendering, the closure will be stripped
81/// automatically.
82///
83/// # Note
84///
85/// You MUST denote the return type of the closure with `|deps| -> ReturnType { ... }`. This
86/// type is used during client side rendering to deserialize the state prepared on the server
87/// side.
88///
89/// Whilst async closure is an unstable feature, the procedural macro will rewrite this to a
90/// closure that returns an async block automatically. You can use this hook with async closure
91/// in stable Rust.
92pub use use_prepared_state_macro as use_prepared_state;
93// With SSR.
94#[doc(hidden)]
95#[cfg(feature = "ssr")]
96pub use yew_macro::use_prepared_state_with_closure as use_prepared_state_macro;
97// Without SSR.
98#[doc(hidden)]
99#[cfg(not(feature = "ssr"))]
100pub use yew_macro::use_prepared_state_without_closure as use_prepared_state_macro;
101
102#[cfg(any(feature = "hydration", feature = "ssr"))]
103mod feat_any_hydration_ssr {
104    use std::marker::PhantomData;
105    #[cfg(feature = "ssr")]
106    use std::rc::Rc;
107
108    use serde::de::DeserializeOwned;
109    use serde::Serialize;
110
111    use crate::functional::PreparedState;
112
113    pub(super) struct PreparedStateBase<T, D>
114    where
115        D: Serialize + DeserializeOwned + PartialEq + 'static,
116        T: Serialize + DeserializeOwned + 'static,
117    {
118        #[cfg(feature = "ssr")]
119        pub state: Option<Rc<T>>,
120        #[cfg(feature = "ssr")]
121        pub deps: Option<Rc<D>>,
122        #[cfg(feature = "hydration")]
123        pub has_buf: bool,
124        pub _marker: PhantomData<(T, D)>,
125    }
126
127    impl<T, D> PreparedState for PreparedStateBase<T, D>
128    where
129        D: Serialize + DeserializeOwned + PartialEq + 'static,
130        T: Serialize + DeserializeOwned + 'static,
131    {
132        #[cfg(feature = "ssr")]
133        fn prepare(&self) -> String {
134            use base64ct::{Base64, Encoding};
135
136            let state = bincode::serialize(&(self.state.as_deref(), self.deps.as_deref()))
137                .expect("failed to prepare state");
138
139            Base64::encode_string(&state)
140        }
141    }
142}
143
144#[cfg(any(feature = "hydration", feature = "ssr"))]
145use feat_any_hydration_ssr::PreparedStateBase;