Update signature of use_prepared_state/use_transitive_state (#3376)

* Update signature of use_prepared_state

* Update signature of use_transitive_state

* Migration guide + example

* bless trybuild tests

* please fmt

* there's one usage here as well

* use_prepared_state_with_suspension needs updates

* updated tests
This commit is contained in:
Muhammad Hamza 2023-08-19 17:58:36 +05:00 committed by GitHub
parent a27076db86
commit 42e1890f03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 162 additions and 87 deletions

View File

@ -18,7 +18,7 @@ async fn fetch_uuid() -> Uuid {
#[function_component] #[function_component]
fn Content() -> HtmlResult { fn Content() -> HtmlResult {
let uuid = use_prepared_state!(async move |_| -> Uuid { fetch_uuid().await }, ())?.unwrap(); let uuid = use_prepared_state!((), async move |_| -> Uuid { fetch_uuid().await })?.unwrap();
Ok(html! { Ok(html! {
<div>{"Random UUID: "}{uuid}</div> <div>{"Random UUID: "}{uuid}</div>

View File

@ -12,13 +12,8 @@ pub struct PreparedState {
impl Parse for PreparedState { impl Parse for PreparedState {
fn parse(input: ParseStream) -> syn::Result<Self> { fn parse(input: ParseStream) -> syn::Result<Self> {
// Reads a closure. // Reads the deps.
let expr: Expr = input.parse()?; let deps = input.parse()?;
let closure = match expr {
Expr::Closure(m) => m,
other => return Err(syn::Error::new_spanned(other, "expected closure")),
};
input.parse::<Token![,]>().map_err(|e| { input.parse::<Token![,]>().map_err(|e| {
syn::Error::new( syn::Error::new(
@ -27,6 +22,14 @@ impl Parse for PreparedState {
) )
})?; })?;
// Reads a closure.
let expr: Expr = input.parse()?;
let closure = match expr {
Expr::Closure(m) => m,
other => return Err(syn::Error::new_spanned(other, "expected closure")),
};
let return_type = match &closure.output { let return_type = match &closure.output {
ReturnType::Default => { ReturnType::Default => {
return Err(syn::Error::new_spanned( return Err(syn::Error::new_spanned(
@ -38,9 +41,6 @@ impl Parse for PreparedState {
ReturnType::Type(_rarrow, ty) => *ty.to_owned(), ReturnType::Type(_rarrow, ty) => *ty.to_owned(),
}; };
// Reads the deps.
let deps = input.parse()?;
if !input.is_empty() { if !input.is_empty() {
let maybe_trailing_comma = input.lookahead1(); let maybe_trailing_comma = input.lookahead1();
@ -107,10 +107,10 @@ impl PreparedState {
match &self.closure.asyncness { match &self.closure.asyncness {
Some(_) => quote! { Some(_) => quote! {
::yew::functional::use_prepared_state_with_suspension::<#rt, _, _, _>(#closure, #deps) ::yew::functional::use_prepared_state_with_suspension::<#rt, _, _, _>(#deps, #closure)
}, },
None => quote! { None => quote! {
::yew::functional::use_prepared_state::<#rt, _, _>(#closure, #deps) ::yew::functional::use_prepared_state::<#rt, _, _>(#deps, #closure)
}, },
} }
} }

View File

@ -12,13 +12,8 @@ pub struct TransitiveState {
impl Parse for TransitiveState { impl Parse for TransitiveState {
fn parse(input: ParseStream) -> syn::Result<Self> { fn parse(input: ParseStream) -> syn::Result<Self> {
// Reads a closure. // Reads the deps.
let expr: Expr = input.parse()?; let deps = input.parse()?;
let closure = match expr {
Expr::Closure(m) => m,
other => return Err(syn::Error::new_spanned(other, "expected closure")),
};
input.parse::<Token![,]>().map_err(|e| { input.parse::<Token![,]>().map_err(|e| {
syn::Error::new( syn::Error::new(
@ -27,6 +22,14 @@ impl Parse for TransitiveState {
) )
})?; })?;
// Reads a closure.
let expr: Expr = input.parse()?;
let closure = match expr {
Expr::Closure(m) => m,
other => return Err(syn::Error::new_spanned(other, "expected closure")),
};
let return_type = match &closure.output { let return_type = match &closure.output {
ReturnType::Default => { ReturnType::Default => {
return Err(syn::Error::new_spanned( return Err(syn::Error::new_spanned(
@ -38,9 +41,6 @@ impl Parse for TransitiveState {
ReturnType::Type(_rarrow, ty) => *ty.to_owned(), ReturnType::Type(_rarrow, ty) => *ty.to_owned(),
}; };
// Reads the deps.
let deps = input.parse()?;
if !input.is_empty() { if !input.is_empty() {
let maybe_trailing_comma = input.lookahead1(); let maybe_trailing_comma = input.lookahead1();
@ -64,7 +64,7 @@ impl TransitiveState {
let closure = &self.closure; let closure = &self.closure;
quote! { quote! {
::yew::functional::use_transitive_state::<#rt, _, _>(#closure, #deps) ::yew::functional::use_transitive_state::<#rt, _, _>(#deps, #closure)
} }
} }

View File

@ -5,12 +5,16 @@ use yew_macro::{use_prepared_state_with_closure, use_prepared_state_without_clos
fn Comp() -> HtmlResult { fn Comp() -> HtmlResult {
use_prepared_state_with_closure!(123)?; use_prepared_state_with_closure!(123)?;
use_prepared_state_with_closure!(|_| { todo!() }, 123)?; use_prepared_state_with_closure!(123, |_| { todo!() })?;
use_prepared_state_with_closure!(|_| -> u32 { todo!() })?; use_prepared_state_with_closure!(|_| -> u32 { todo!() })?;
use_prepared_state_with_closure!(|_| -> u32 { todo!() }, 123)?;
use_prepared_state_with_closure!(async |_| -> u32 { todo!() })?; use_prepared_state_with_closure!(async |_| -> u32 { todo!() })?;
use_prepared_state_with_closure!(|_| { todo!() }, 123)?;
Ok(Html::default()) Ok(Html::default())
} }
@ -18,10 +22,14 @@ fn Comp() -> HtmlResult {
fn Comp2() -> HtmlResult { fn Comp2() -> HtmlResult {
use_prepared_state_without_closure!(123)?; use_prepared_state_without_closure!(123)?;
use_prepared_state_without_closure!(123, |_| { todo!() })?;
use_prepared_state_without_closure!(|_| { todo!() }, 123)?; use_prepared_state_without_closure!(|_| { todo!() }, 123)?;
use_prepared_state_without_closure!(|_| -> u32 { todo!() })?; use_prepared_state_without_closure!(|_| -> u32 { todo!() })?;
use_prepared_state_without_closure!(|_| -> u32 { todo!() }, 123)?;
use_prepared_state_without_closure!(async |_| -> u32 { todo!() })?; use_prepared_state_without_closure!(async |_| -> u32 { todo!() })?;
Ok(Html::default()) Ok(Html::default())

View File

@ -1,14 +1,16 @@
error: expected closure error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_prepared_state-fail.rs:6:38 --> tests/hook_macro/use_prepared_state-fail.rs:6:5
| |
6 | use_prepared_state_with_closure!(123)?; 6 | use_prepared_state_with_closure!(123)?;
| ^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `use_prepared_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle. error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle.
--> tests/hook_macro/use_prepared_state-fail.rs:8:38 --> tests/hook_macro/use_prepared_state-fail.rs:8:43
| |
8 | use_prepared_state_with_closure!(|_| { todo!() }, 123)?; 8 | use_prepared_state_with_closure!(123, |_| { todo!() })?;
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: this hook takes 2 arguments but 1 argument was supplied error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_prepared_state-fail.rs:10:5 --> tests/hook_macro/use_prepared_state-fail.rs:10:5
@ -18,38 +20,64 @@ error: this hook takes 2 arguments but 1 argument was supplied
| |
= note: this error originates in the macro `use_prepared_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `use_prepared_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this hook takes 2 arguments but 1 argument was supplied error: expected closure
--> tests/hook_macro/use_prepared_state-fail.rs:12:5 --> tests/hook_macro/use_prepared_state-fail.rs:12:62
| |
12 | use_prepared_state_with_closure!(async |_| -> u32 { todo!() })?; 12 | use_prepared_state_with_closure!(|_| -> u32 { todo!() }, 123)?;
| ^^^
error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_prepared_state-fail.rs:14:5
|
14 | use_prepared_state_with_closure!(async |_| -> u32 { todo!() })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this error originates in the macro `use_prepared_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `use_prepared_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected closure error: expected closure
--> tests/hook_macro/use_prepared_state-fail.rs:19:41 --> tests/hook_macro/use_prepared_state-fail.rs:16:55
| |
19 | use_prepared_state_without_closure!(123)?; 16 | use_prepared_state_with_closure!(|_| { todo!() }, 123)?;
| ^^^ | ^^^
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle.
--> tests/hook_macro/use_prepared_state-fail.rs:21:41
|
21 | use_prepared_state_without_closure!(|_| { todo!() }, 123)?;
| ^^^^^^^^^^^^^^^
error: this hook takes 2 arguments but 1 argument was supplied error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_prepared_state-fail.rs:23:5 --> tests/hook_macro/use_prepared_state-fail.rs:23:5
| |
23 | use_prepared_state_without_closure!(|_| -> u32 { todo!() })?; 23 | use_prepared_state_without_closure!(123)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `use_prepared_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle.
--> tests/hook_macro/use_prepared_state-fail.rs:25:46
|
25 | use_prepared_state_without_closure!(123, |_| { todo!() })?;
| ^^^^^^^^^^^^^^^
error: expected closure
--> tests/hook_macro/use_prepared_state-fail.rs:27:58
|
27 | use_prepared_state_without_closure!(|_| { todo!() }, 123)?;
| ^^^
error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_prepared_state-fail.rs:29:5
|
29 | use_prepared_state_without_closure!(|_| -> u32 { todo!() })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this error originates in the macro `use_prepared_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `use_prepared_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this hook takes 2 arguments but 1 argument was supplied error: expected closure
--> tests/hook_macro/use_prepared_state-fail.rs:25:5 --> tests/hook_macro/use_prepared_state-fail.rs:31:65
| |
25 | use_prepared_state_without_closure!(async |_| -> u32 { todo!() })?; 31 | use_prepared_state_without_closure!(|_| -> u32 { todo!() }, 123)?;
| ^^^
error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_prepared_state-fail.rs:33:5
|
33 | use_prepared_state_without_closure!(async |_| -> u32 { todo!() })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this error originates in the macro `use_prepared_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `use_prepared_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -7,8 +7,12 @@ fn Comp() -> HtmlResult {
use_transitive_state_with_closure!(|_| { todo!() }, 123)?; use_transitive_state_with_closure!(|_| { todo!() }, 123)?;
use_transitive_state_with_closure!(123, |_| { todo!() })?;
use_transitive_state_with_closure!(|_| -> u32 { todo!() })?; use_transitive_state_with_closure!(|_| -> u32 { todo!() })?;
use_transitive_state_with_closure!(|_| -> u32 { todo!() }, 123)?;
Ok(Html::default()) Ok(Html::default())
} }
@ -18,8 +22,12 @@ fn Comp2() -> HtmlResult {
use_transitive_state_without_closure!(|_| { todo!() }, 123)?; use_transitive_state_without_closure!(|_| { todo!() }, 123)?;
use_transitive_state_without_closure!(123, |_| { todo!() })?;
use_transitive_state_without_closure!(|_| -> u32 { todo!() })?; use_transitive_state_without_closure!(|_| -> u32 { todo!() })?;
use_transitive_state_without_closure!(|_| -> u32 { todo!() }, 123)?;
Ok(Html::default()) Ok(Html::default())
} }

View File

@ -1,39 +1,67 @@
error: expected closure error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_transitive_state-fail.rs:6:40 --> tests/hook_macro/use_transitive_state-fail.rs:6:5
| |
6 | use_transitive_state_with_closure!(123)?; 6 | use_transitive_state_with_closure!(123)?;
| ^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `use_transitive_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle. error: expected closure
--> tests/hook_macro/use_transitive_state-fail.rs:8:40 --> tests/hook_macro/use_transitive_state-fail.rs:8:57
| |
8 | use_transitive_state_with_closure!(|_| { todo!() }, 123)?; 8 | use_transitive_state_with_closure!(|_| { todo!() }, 123)?;
| ^^^^^^^^^^^^^^^ | ^^^
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle.
--> tests/hook_macro/use_transitive_state-fail.rs:10:45
|
10 | use_transitive_state_with_closure!(123, |_| { todo!() })?;
| ^^^^^^^^^^^^^^^
error: this hook takes 2 arguments but 1 argument was supplied error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_transitive_state-fail.rs:10:5 --> tests/hook_macro/use_transitive_state-fail.rs:12:5
| |
10 | use_transitive_state_with_closure!(|_| -> u32 { todo!() })?; 12 | use_transitive_state_with_closure!(|_| -> u32 { todo!() })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this error originates in the macro `use_transitive_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `use_transitive_state_with_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected closure error: expected closure
--> tests/hook_macro/use_transitive_state-fail.rs:17:43 --> tests/hook_macro/use_transitive_state-fail.rs:14:64
| |
17 | use_transitive_state_without_closure!(123)?; 14 | use_transitive_state_with_closure!(|_| -> u32 { todo!() }, 123)?;
| ^^^ | ^^^
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle.
--> tests/hook_macro/use_transitive_state-fail.rs:19:43
|
19 | use_transitive_state_without_closure!(|_| { todo!() }, 123)?;
| ^^^^^^^^^^^^^^^
error: this hook takes 2 arguments but 1 argument was supplied error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_transitive_state-fail.rs:21:5 --> tests/hook_macro/use_transitive_state-fail.rs:21:5
| |
21 | use_transitive_state_without_closure!(|_| -> u32 { todo!() })?; 21 | use_transitive_state_without_closure!(123)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `use_transitive_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected closure
--> tests/hook_macro/use_transitive_state-fail.rs:23:60
|
23 | use_transitive_state_without_closure!(|_| { todo!() }, 123)?;
| ^^^
error: You must specify a return type for this closure. This is used when the closure is omitted from the client side rendering bundle.
--> tests/hook_macro/use_transitive_state-fail.rs:25:48
|
25 | use_transitive_state_without_closure!(123, |_| { todo!() })?;
| ^^^^^^^^^^^^^^^
error: this hook takes 2 arguments but 1 argument was supplied
--> tests/hook_macro/use_transitive_state-fail.rs:27:5
|
27 | use_transitive_state_without_closure!(|_| -> u32 { todo!() })?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: this error originates in the macro `use_transitive_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `use_transitive_state_without_closure` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected closure
--> tests/hook_macro/use_transitive_state-fail.rs:29:67
|
29 | use_transitive_state_without_closure!(|_| -> u32 { todo!() }, 123)?;
| ^^^

View File

@ -13,8 +13,8 @@ use crate::suspense::SuspensionResult;
#[doc(hidden)] #[doc(hidden)]
pub fn use_prepared_state<T, D, F>( pub fn use_prepared_state<T, D, F>(
f: F,
deps: D, deps: D,
f: F,
) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>> ) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>>
where where
D: Serialize + DeserializeOwned + PartialEq + 'static, D: Serialize + DeserializeOwned + PartialEq + 'static,
@ -41,7 +41,7 @@ where
fn run(self, ctx: &mut HookContext) -> Self::Output { fn run(self, ctx: &mut HookContext) -> Self::Output {
match ctx.creation_mode { match ctx.creation_mode {
RenderMode::Ssr => feat_ssr::use_prepared_state(self.f, self.deps).run(ctx), RenderMode::Ssr => feat_ssr::use_prepared_state(self.deps, self.f).run(ctx),
_ => feat_hydration::use_prepared_state(self.deps).run(ctx), _ => feat_hydration::use_prepared_state(self.deps).run(ctx),
} }
} }
@ -52,8 +52,8 @@ where
#[doc(hidden)] #[doc(hidden)]
pub fn use_prepared_state_with_suspension<T, D, F, U>( pub fn use_prepared_state_with_suspension<T, D, F, U>(
f: F,
deps: D, deps: D,
f: F,
) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>> ) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>>
where where
D: Serialize + DeserializeOwned + PartialEq + 'static, D: Serialize + DeserializeOwned + PartialEq + 'static,
@ -84,7 +84,7 @@ where
fn run(self, ctx: &mut HookContext) -> Self::Output { fn run(self, ctx: &mut HookContext) -> Self::Output {
match ctx.creation_mode { match ctx.creation_mode {
RenderMode::Ssr => { RenderMode::Ssr => {
feat_ssr::use_prepared_state_with_suspension(self.f, self.deps).run(ctx) feat_ssr::use_prepared_state_with_suspension(self.deps, self.f).run(ctx)
} }
_ => feat_hydration::use_prepared_state(self.deps).run(ctx), _ => feat_hydration::use_prepared_state(self.deps).run(ctx),
} }

View File

@ -14,8 +14,8 @@ use crate::suspense::{Suspension, SuspensionResult};
#[doc(hidden)] #[doc(hidden)]
pub fn use_prepared_state<T, D, F>( pub fn use_prepared_state<T, D, F>(
f: F,
deps: D, deps: D,
f: F,
) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>> ) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>>
where where
D: Serialize + DeserializeOwned + PartialEq + 'static, D: Serialize + DeserializeOwned + PartialEq + 'static,
@ -69,8 +69,8 @@ where
#[doc(hidden)] #[doc(hidden)]
pub fn use_prepared_state_with_suspension<T, D, F, U>( pub fn use_prepared_state_with_suspension<T, D, F, U>(
f: F,
deps: D, deps: D,
f: F,
) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>> ) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>>
where where
D: Serialize + DeserializeOwned + PartialEq + 'static, D: Serialize + DeserializeOwned + PartialEq + 'static,

View File

@ -39,7 +39,7 @@ pub use feat_ssr::*;
/// use yew::suspense::SuspensionResult; /// use yew::suspense::SuspensionResult;
/// ///
/// #[hook] /// #[hook]
/// pub fn use_prepared_state<T, D, F>(f: F, deps: D) -> SuspensionResult<Option<Rc<T>>> /// pub fn use_prepared_state<T, D, F>(deps: D, f: F) -> SuspensionResult<Option<Rc<T>>>
/// where /// where
/// D: Serialize + DeserializeOwned + PartialEq + 'static, /// D: Serialize + DeserializeOwned + PartialEq + 'static,
/// T: Serialize + DeserializeOwned + 'static, /// T: Serialize + DeserializeOwned + 'static,
@ -63,8 +63,8 @@ pub use feat_ssr::*;
/// ///
/// #[hook] /// #[hook]
/// pub fn use_prepared_state<T, D, F, U>( /// pub fn use_prepared_state<T, D, F, U>(
/// f: F,
/// deps: D, /// deps: D,
/// f: F,
/// ) -> SuspensionResult<Option<Rc<T>>> /// ) -> SuspensionResult<Option<Rc<T>>>
/// where /// where
/// D: Serialize + DeserializeOwned + PartialEq + 'static, /// D: Serialize + DeserializeOwned + PartialEq + 'static,

View File

@ -12,8 +12,8 @@ use crate::suspense::SuspensionResult;
#[doc(hidden)] #[doc(hidden)]
pub fn use_transitive_state<T, D, F>( pub fn use_transitive_state<T, D, F>(
f: F,
deps: D, deps: D,
f: F,
) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>> ) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>>
where where
D: Serialize + DeserializeOwned + PartialEq + 'static, D: Serialize + DeserializeOwned + PartialEq + 'static,
@ -40,7 +40,7 @@ where
fn run(self, ctx: &mut HookContext) -> Self::Output { fn run(self, ctx: &mut HookContext) -> Self::Output {
match ctx.creation_mode { match ctx.creation_mode {
RenderMode::Ssr => feat_ssr::use_transitive_state(self.f, self.deps).run(ctx), RenderMode::Ssr => feat_ssr::use_transitive_state(self.deps, self.f).run(ctx),
_ => feat_hydration::use_transitive_state(self.deps).run(ctx), _ => feat_hydration::use_transitive_state(self.deps).run(ctx),
} }
} }

View File

@ -39,8 +39,8 @@ where
#[doc(hidden)] #[doc(hidden)]
pub fn use_transitive_state<T, D, F>( pub fn use_transitive_state<T, D, F>(
f: F,
deps: D, deps: D,
f: F,
) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>> ) -> impl Hook<Output = SuspensionResult<Option<Rc<T>>>>
where where
D: Serialize + DeserializeOwned + PartialEq + 'static, D: Serialize + DeserializeOwned + PartialEq + 'static,

View File

@ -27,7 +27,7 @@ pub use feat_ssr::*;
/// During hydration, it will only return `Ok(Some(Rc<T>))` if the component is hydrated from a /// During hydration, it will only return `Ok(Some(Rc<T>))` if the component is hydrated from a
/// server-side rendering artifact and its dependency value matches. /// server-side rendering artifact and its dependency value matches.
/// ///
/// `let state = use_transitive_state!(|deps| -> ReturnType { ... }, deps);` /// `let state = use_transitive_state!(deps, |deps| -> ReturnType { ... });`
/// ///
/// It has the following function signature: /// It has the following function signature:
/// ///
@ -39,7 +39,7 @@ pub use feat_ssr::*;
/// use yew::suspense::SuspensionResult; /// use yew::suspense::SuspensionResult;
/// ///
/// #[hook] /// #[hook]
/// pub fn use_transitive_state<T, D, F>(f: F, deps: D) -> SuspensionResult<Option<Rc<T>>> /// pub fn use_transitive_state<T, D, F>(deps: D, f: F) -> SuspensionResult<Option<Rc<T>>>
/// where /// where
/// D: Serialize + DeserializeOwned + PartialEq + 'static, /// D: Serialize + DeserializeOwned + PartialEq + 'static,
/// T: Serialize + DeserializeOwned + 'static, /// T: Serialize + DeserializeOwned + 'static,

View File

@ -18,7 +18,7 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
async fn use_prepared_state_works() { async fn use_prepared_state_works() {
#[function_component] #[function_component]
fn Comp() -> HtmlResult { fn Comp() -> HtmlResult {
let ctr = use_prepared_state!(|_| -> u32 { 12345 }, ())?.unwrap_or_default(); let ctr = use_prepared_state!((), |_| -> u32 { 12345 })?.unwrap_or_default();
Ok(html! { Ok(html! {
<div> <div>
@ -68,7 +68,7 @@ async fn use_prepared_state_works() {
async fn use_prepared_state_with_suspension_works() { async fn use_prepared_state_with_suspension_works() {
#[function_component] #[function_component]
fn Comp() -> HtmlResult { fn Comp() -> HtmlResult {
let ctr = use_prepared_state!(async move |_| -> u32 { 12345 }, ())?.unwrap_or_default(); let ctr = use_prepared_state!((), async move |_| -> u32 { 12345 })?.unwrap_or_default();
Ok(html! { Ok(html! {
<div> <div>

View File

@ -17,7 +17,7 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
async fn use_transitive_state_works() { async fn use_transitive_state_works() {
#[function_component] #[function_component]
fn Comp() -> HtmlResult { fn Comp() -> HtmlResult {
let ctr = use_transitive_state!(|_| -> u32 { 12345 }, ())?.unwrap_or_default(); let ctr = use_transitive_state!((), |_| -> u32 { 12345 })?.unwrap_or_default();
Ok(html! { Ok(html! {
<div> <div>

View File

@ -140,12 +140,9 @@ async fn bench_concurrent_task() -> Duration {
#[function_component] #[function_component]
fn Comp() -> HtmlResult { fn Comp() -> HtmlResult {
let _state = use_prepared_state!( let _state = use_prepared_state!((), async move |_| -> () {
async move |_| -> () { sleep(Duration::from_secs(1)).await;
sleep(Duration::from_secs(1)).await; })?;
},
()
)?;
Ok(Html::default()) Ok(Html::default())
} }

View File

@ -27,6 +27,12 @@ sg --pattern 'use_memo($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_memo($DEPENDE
sg --pattern 'use_future_with_deps($CALLBACK,$$$DEPENDENCIES)' --rewrite 'use_effect_with($$$DEPENDENCIES, $CALLBACK)' -l rs -i sg --pattern 'use_future_with_deps($CALLBACK,$$$DEPENDENCIES)' --rewrite 'use_effect_with($$$DEPENDENCIES, $CALLBACK)' -l rs -i
sg --pattern 'use_future_with($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_effect_with($DEPENDENCIES,$$$CALLBACK)' -l rs -i sg --pattern 'use_future_with($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_effect_with($DEPENDENCIES,$$$CALLBACK)' -l rs -i
sg --pattern 'use_transitive_state!($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_transitive_state!($DEPENDENCIES,$$$CALLBACK)' -l rs -i
sg --pattern 'use_transitive_state!($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_transitive_state!($DEPENDENCIES,$$$CALLBACK)' -l rs -i
sg --pattern 'use_prepared_state!($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_prepared_state!($DEPENDENCIES,$$$CALLBACK)' -l rs -i
sg --pattern 'use_prepared_state!($DEPENDENCIES,,$$$CALLBACK)' --rewrite 'use_prepared_state!($DEPENDENCIES,$$$CALLBACK)' -l rs -i
``` ```
### Reasoning ### Reasoning