From 94a1822c0c0aca18680d5fda23fb1f9736bca961 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Mon, 20 Jun 2022 01:35:59 +0500 Subject: [PATCH 01/10] Nightly features --- packages/yew-macro/Cargo.toml | 1 + .../yew-macro/src/html_tree/html_element.rs | 18 +++++++--- packages/yew-macro/src/lib.rs | 2 ++ packages/yew-macro/src/use_prepared_state.rs | 10 +++++- packages/yew/Cargo.toml | 1 + .../src/functional/hooks/use_force_update.rs | 30 ++++++++++++---- .../yew/src/functional/hooks/use_reducer.rs | 35 +++++++++++++++++++ packages/yew/src/lib.rs | 1 + 8 files changed, 86 insertions(+), 12 deletions(-) diff --git a/packages/yew-macro/Cargo.toml b/packages/yew-macro/Cargo.toml index ae17548fbb0..5cd5679ad2a 100644 --- a/packages/yew-macro/Cargo.toml +++ b/packages/yew-macro/Cargo.toml @@ -35,3 +35,4 @@ yew = { path = "../yew" } [features] lints = [] +nightly = [] diff --git a/packages/yew-macro/src/html_tree/html_element.rs b/packages/yew-macro/src/html_tree/html_element.rs index a6e9e9e179a..8b981a10d1c 100644 --- a/packages/yew-macro/src/html_tree/html_element.rs +++ b/packages/yew-macro/src/html_tree/html_element.rs @@ -387,6 +387,18 @@ impl ToTokens for HtmlElement { }} }); + #[cfg(feature = "nightly")] + let invalid_void_tag_msg_start = { + let span = vtag.span().unwrap(); + let source_file = span.source_file().path(); + let source_file = source_file.display(); + let start = span.start(); + format!("[{}:{}:{}] ", source_file, start.line, start.column) + }; + + #[cfg(not(feature = "nightly"))] + let invalid_void_tag_msg_start = ""; + // this way we get a nice error message (with the correct span) when the expression // doesn't return a valid value quote_spanned! {expr.span()=> { @@ -442,10 +454,6 @@ impl ToTokens for HtmlElement { // These are the runtime-checks exclusive to dynamic tags. // For literal tags this is already done at compile-time. // - // When Span::source_file Span::start get stabilised or yew-macro introduces a - // nightly feature flag we should expand the panic message to contain the exact - // location of the dynamic tag. - // // check void element if !#vtag.children().is_empty() { ::std::debug_assert!( @@ -453,7 +461,7 @@ impl ToTokens for HtmlElement { "area" | "base" | "br" | "col" | "embed" | "hr" | "img" | "input" | "link" | "meta" | "param" | "source" | "track" | "wbr" ), - "a dynamic tag tried to create a `<{0}>` tag with children. `<{0}>` is a void element which can't have any children.", + concat!(#invalid_void_tag_msg_start, "a dynamic tag tried to create a `<{0}>` tag with children. `<{0}>` is a void element which can't have any children."), #vtag.tag(), ); } diff --git a/packages/yew-macro/src/lib.rs b/packages/yew-macro/src/lib.rs index e5a50ab2250..5822f0325ff 100644 --- a/packages/yew-macro/src/lib.rs +++ b/packages/yew-macro/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "nightly", feature(proc_macro_span))] + //! This crate provides Yew's procedural macro `html!` which allows using JSX-like syntax //! for generating html and the `Properties` derive macro for deriving the `Properties` trait //! for components. diff --git a/packages/yew-macro/src/use_prepared_state.rs b/packages/yew-macro/src/use_prepared_state.rs index c94240aab1c..ff062b11450 100644 --- a/packages/yew-macro/src/use_prepared_state.rs +++ b/packages/yew-macro/src/use_prepared_state.rs @@ -1,7 +1,7 @@ use proc_macro2::TokenStream; use quote::quote; use syn::parse::{Parse, ParseStream}; -use syn::{parse_quote, Expr, ExprClosure, ReturnType, Token, Type}; +use syn::{Expr, ExprClosure, ReturnType, Token, Type}; #[derive(Debug)] pub struct PreparedState { @@ -59,7 +59,10 @@ impl Parse for PreparedState { impl PreparedState { // Async closure is not stable, so we rewrite it to clsoure + async block + #[cfg(feature = "nightly")] pub fn rewrite_to_closure_with_async_block(&self) -> ExprClosure { + use syn::parse_quote; + let async_token = match &self.closure.asyncness { Some(m) => m, None => return self.closure.clone(), @@ -87,6 +90,11 @@ impl PreparedState { closure } + #[cfg(not(feature = "nightly"))] + pub fn rewrite_to_closure_with_async_block(&self) -> ExprClosure { + self.closure.clone() + } + pub fn to_token_stream_with_closure(&self) -> TokenStream { let deps = &self.deps; let rt = &self.return_type; diff --git a/packages/yew/Cargo.toml b/packages/yew/Cargo.toml index 74d8234090f..a6e6f650d53 100644 --- a/packages/yew/Cargo.toml +++ b/packages/yew/Cargo.toml @@ -96,6 +96,7 @@ features = [ ssr = ["futures", "html-escape", "base64ct", "bincode"] # dep:html-escape csr = [] hydration = ["csr", "bincode"] +nightly = ["yew-macro/nightly"] default = [] [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index 4f05f6d0abc..52d989aca8a 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -23,12 +23,30 @@ impl UseForceUpdate { } } -// #![feature(fn_traits)] // required nightly feature to make UseForceUpdate callable directly -// impl Fn<()> for UseForceUpdate { -// extern "rust-call" fn call(&self, _args: ()) { -// self.force_update() -// } -// } +#[cfg(feature = "nightly")] +mod feat_nightly { + use super::*; + + impl FnOnce<()> for UseForceUpdate { + type Output = (); + + extern "rust-call" fn call_once(self, _args: ()) -> Self::Output { + self.force_update() + } + } + + impl FnMut<()> for UseForceUpdate { + extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output { + self.force_update() + } + } + + impl Fn<()> for UseForceUpdate { + extern "rust-call" fn call(&self, _args: ()) -> Self::Output { + self.force_update() + } + } +} /// This hook is used to manually force a function component to re-render. /// diff --git a/packages/yew/src/functional/hooks/use_reducer.rs b/packages/yew/src/functional/hooks/use_reducer.rs index 15ae1af68d7..53ac6854f8c 100644 --- a/packages/yew/src/functional/hooks/use_reducer.rs +++ b/packages/yew/src/functional/hooks/use_reducer.rs @@ -95,6 +95,41 @@ where } } + +#[cfg(feature = "nightly")] +mod feat_nightly { + use super::*; + + impl FnOnce<(T::Action,)> for UseReducerHandle + where + T: Reducible, + { + type Output = (); + + extern "rust-call" fn call_once(self, args: (T::Action,)) -> Self::Output { + self.dispatch(args.0) + } + } + + impl FnMut<(T::Action,)> for UseReducerHandle + where + T: Reducible, + { + extern "rust-call" fn call_mut(&mut self, args: (T::Action,)) -> Self::Output { + self.dispatch(args.0) + } + } + + impl Fn<(T::Action,)> for UseReducerHandle + where + T: Reducible, + { + extern "rust-call" fn call(&self, args: (T::Action,)) -> Self::Output { + self.dispatch(args.0) + } + } +} + /// Dispatcher handle for [`use_reducer`] and [`use_reducer_eq`] hook pub struct UseReducerDispatcher where diff --git a/packages/yew/src/lib.rs b/packages/yew/src/lib.rs index b9bdd9eb257..0a2590f9c99 100644 --- a/packages/yew/src/lib.rs +++ b/packages/yew/src/lib.rs @@ -1,6 +1,7 @@ #![allow(clippy::needless_doctest_main)] #![doc(html_logo_url = "https://yew.rs/img/logo.png")] #![cfg_attr(documenting, feature(doc_cfg))] +#![cfg_attr(feature = "nightly", feature(fn_traits, unboxed_closures))] //! # Yew Framework - API Documentation //! From efc59acb7fe995709c6532952c333cd67c495917 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Mon, 20 Jun 2022 01:42:15 +0500 Subject: [PATCH 02/10] Tests --- .../src/functional/hooks/use_force_update.rs | 12 +++++ .../yew/src/functional/hooks/use_reducer.rs | 52 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index 52d989aca8a..673599b674b 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -111,3 +111,15 @@ pub fn use_force_update() -> impl Hook { UseRerenderHook } + +#[cfg(all(test, feature = "nightly"))] +mod nightly_test { + use yew::prelude::*; + + #[function_component] + fn ManuallyUpdatedDate() -> Html { + let trigger = use_force_update(); + let _ = move || { trigger() }; + html! {} + } +} diff --git a/packages/yew/src/functional/hooks/use_reducer.rs b/packages/yew/src/functional/hooks/use_reducer.rs index 53ac6854f8c..b8251f4750e 100644 --- a/packages/yew/src/functional/hooks/use_reducer.rs +++ b/packages/yew/src/functional/hooks/use_reducer.rs @@ -363,3 +363,55 @@ where { use_reducer_base(init_fn, T::ne) } + +#[cfg(all(test, feature = "nightly"))] +mod nightly_test { + use yew::prelude::*; + use std::rc::Rc; + + /// reducer's Action + enum CounterAction { + Double, + } + + /// reducer's State + struct CounterState { + counter: i32, + } + + impl Default for CounterState { + fn default() -> Self { + Self { counter: 1 } + } + } + + impl Reducible for CounterState { + /// Reducer Action Type + type Action = CounterAction; + + /// Reducer Function + fn reduce(self: Rc, action: Self::Action) -> Rc { + let next_ctr = match action { + CounterAction::Double => self.counter * 2, + }; + + Self { counter: next_ctr }.into() + } + } + + #[function_component(UseReducer)] + fn reducer() -> Html { + // The use_reducer hook takes an initialization function which will be called only once. + let counter = use_reducer(CounterState::default); + + let double_onclick = { + let counter = counter.clone(); + Callback::from(move |_| counter(CounterAction::Double)) + }; + + html! { +
{ counter.counter }
+ + } + } +} From b8aa49565691aabf9fa2628adddb19a20b89dbed Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Mon, 20 Jun 2022 02:10:21 +0500 Subject: [PATCH 03/10] Fix tests --- packages/yew-macro/src/use_prepared_state.rs | 6 ++--- .../src/functional/hooks/use_force_update.rs | 2 +- .../yew/src/functional/hooks/use_reducer.rs | 22 ++++++++++--------- packages/yew/src/lib.rs | 5 ++++- packages/yew/tests/use_prepared_state.rs | 3 ++- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/yew-macro/src/use_prepared_state.rs b/packages/yew-macro/src/use_prepared_state.rs index ff062b11450..e860277a9f8 100644 --- a/packages/yew-macro/src/use_prepared_state.rs +++ b/packages/yew-macro/src/use_prepared_state.rs @@ -58,8 +58,8 @@ impl Parse for PreparedState { } impl PreparedState { - // Async closure is not stable, so we rewrite it to clsoure + async block - #[cfg(feature = "nightly")] + // Async closure is not stable, so we rewrite it to closure + async block + #[cfg(not(feature = "nightly"))] pub fn rewrite_to_closure_with_async_block(&self) -> ExprClosure { use syn::parse_quote; @@ -90,7 +90,7 @@ impl PreparedState { closure } - #[cfg(not(feature = "nightly"))] + #[cfg(feature = "nightly")] pub fn rewrite_to_closure_with_async_block(&self) -> ExprClosure { self.closure.clone() } diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index 673599b674b..ef127f81917 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -119,7 +119,7 @@ mod nightly_test { #[function_component] fn ManuallyUpdatedDate() -> Html { let trigger = use_force_update(); - let _ = move || { trigger() }; + let _ = move || trigger(); html! {} } } diff --git a/packages/yew/src/functional/hooks/use_reducer.rs b/packages/yew/src/functional/hooks/use_reducer.rs index b8251f4750e..6f99c844627 100644 --- a/packages/yew/src/functional/hooks/use_reducer.rs +++ b/packages/yew/src/functional/hooks/use_reducer.rs @@ -95,14 +95,13 @@ where } } - #[cfg(feature = "nightly")] mod feat_nightly { use super::*; impl FnOnce<(T::Action,)> for UseReducerHandle - where - T: Reducible, + where + T: Reducible, { type Output = (); @@ -112,8 +111,8 @@ mod feat_nightly { } impl FnMut<(T::Action,)> for UseReducerHandle - where - T: Reducible, + where + T: Reducible, { extern "rust-call" fn call_mut(&mut self, args: (T::Action,)) -> Self::Output { self.dispatch(args.0) @@ -121,8 +120,8 @@ mod feat_nightly { } impl Fn<(T::Action,)> for UseReducerHandle - where - T: Reducible, + where + T: Reducible, { extern "rust-call" fn call(&self, args: (T::Action,)) -> Self::Output { self.dispatch(args.0) @@ -366,9 +365,10 @@ where #[cfg(all(test, feature = "nightly"))] mod nightly_test { - use yew::prelude::*; use std::rc::Rc; + use yew::prelude::*; + /// reducer's Action enum CounterAction { Double, @@ -410,8 +410,10 @@ mod nightly_test { }; html! { -
{ counter.counter }
- + <> +
{ counter.counter }
+ + } } } diff --git a/packages/yew/src/lib.rs b/packages/yew/src/lib.rs index 0a2590f9c99..a8b30c966c2 100644 --- a/packages/yew/src/lib.rs +++ b/packages/yew/src/lib.rs @@ -1,7 +1,10 @@ #![allow(clippy::needless_doctest_main)] #![doc(html_logo_url = "https://yew.rs/img/logo.png")] #![cfg_attr(documenting, feature(doc_cfg))] -#![cfg_attr(feature = "nightly", feature(fn_traits, unboxed_closures))] +#![cfg_attr( + feature = "nightly", + feature(fn_traits, async_closure, unboxed_closures) +)] //! # Yew Framework - API Documentation //! diff --git a/packages/yew/tests/use_prepared_state.rs b/packages/yew/tests/use_prepared_state.rs index 93c52e71b06..2263aff4f46 100644 --- a/packages/yew/tests/use_prepared_state.rs +++ b/packages/yew/tests/use_prepared_state.rs @@ -1,5 +1,6 @@ #![cfg(target_arch = "wasm32")] #![cfg(feature = "hydration")] +#![cfg_attr(feature = "nightly", feature(async_closure))] use std::time::Duration; @@ -67,7 +68,7 @@ async fn use_prepared_state_works() { async fn use_prepared_state_with_suspension_works() { #[function_component] fn Comp() -> HtmlResult { - let ctr = use_prepared_state!(async |_| -> u32 { 12345 }, ())?.unwrap_or_default(); + let ctr = use_prepared_state!(async move |_| -> u32 { 12345 }, ())?.unwrap_or_default(); Ok(html! {
From 893fb1826522b721c792dd22179a5c2ec4654544 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Mon, 20 Jun 2022 02:13:54 +0500 Subject: [PATCH 04/10] Don't invent new syntax --- examples/simple_ssr/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple_ssr/src/lib.rs b/examples/simple_ssr/src/lib.rs index dd291b644a8..1204af904ec 100644 --- a/examples/simple_ssr/src/lib.rs +++ b/examples/simple_ssr/src/lib.rs @@ -18,7 +18,7 @@ async fn fetch_uuid() -> Uuid { #[function_component] fn Content() -> HtmlResult { - let uuid = use_prepared_state!(async |_| -> Uuid { fetch_uuid().await }, ())?.unwrap(); + let uuid = use_prepared_state!(async move |_| -> Uuid { fetch_uuid().await }, ())?.unwrap(); Ok(html! {
{"Random UUID: "}{uuid}
From 6d9bd6aecf477a4c9950f431ef9b712ac8e79158 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Tue, 21 Jun 2022 00:22:56 +0500 Subject: [PATCH 05/10] Do not impl Fn for UseReducerHandle --- .../yew/src/functional/hooks/use_reducer.rs | 89 ------------------- 1 file changed, 89 deletions(-) diff --git a/packages/yew/src/functional/hooks/use_reducer.rs b/packages/yew/src/functional/hooks/use_reducer.rs index 6f99c844627..15ae1af68d7 100644 --- a/packages/yew/src/functional/hooks/use_reducer.rs +++ b/packages/yew/src/functional/hooks/use_reducer.rs @@ -95,40 +95,6 @@ where } } -#[cfg(feature = "nightly")] -mod feat_nightly { - use super::*; - - impl FnOnce<(T::Action,)> for UseReducerHandle - where - T: Reducible, - { - type Output = (); - - extern "rust-call" fn call_once(self, args: (T::Action,)) -> Self::Output { - self.dispatch(args.0) - } - } - - impl FnMut<(T::Action,)> for UseReducerHandle - where - T: Reducible, - { - extern "rust-call" fn call_mut(&mut self, args: (T::Action,)) -> Self::Output { - self.dispatch(args.0) - } - } - - impl Fn<(T::Action,)> for UseReducerHandle - where - T: Reducible, - { - extern "rust-call" fn call(&self, args: (T::Action,)) -> Self::Output { - self.dispatch(args.0) - } - } -} - /// Dispatcher handle for [`use_reducer`] and [`use_reducer_eq`] hook pub struct UseReducerDispatcher where @@ -362,58 +328,3 @@ where { use_reducer_base(init_fn, T::ne) } - -#[cfg(all(test, feature = "nightly"))] -mod nightly_test { - use std::rc::Rc; - - use yew::prelude::*; - - /// reducer's Action - enum CounterAction { - Double, - } - - /// reducer's State - struct CounterState { - counter: i32, - } - - impl Default for CounterState { - fn default() -> Self { - Self { counter: 1 } - } - } - - impl Reducible for CounterState { - /// Reducer Action Type - type Action = CounterAction; - - /// Reducer Function - fn reduce(self: Rc, action: Self::Action) -> Rc { - let next_ctr = match action { - CounterAction::Double => self.counter * 2, - }; - - Self { counter: next_ctr }.into() - } - } - - #[function_component(UseReducer)] - fn reducer() -> Html { - // The use_reducer hook takes an initialization function which will be called only once. - let counter = use_reducer(CounterState::default); - - let double_onclick = { - let counter = counter.clone(); - Callback::from(move |_| counter(CounterAction::Double)) - }; - - html! { - <> -
{ counter.counter }
- - - } - } -} From 761dbb0f8bb7c280054d55dcc724f08604ee4ece Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Tue, 21 Jun 2022 00:48:04 +0500 Subject: [PATCH 06/10] Simplify UseForceUpdateHandle --- .../src/functional/hooks/use_force_update.rs | 65 ++----------------- 1 file changed, 4 insertions(+), 61 deletions(-) diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index ef127f81917..f428c09491b 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -1,52 +1,9 @@ -use std::fmt; - use super::{Hook, HookContext}; use crate::functional::ReRender; /// A handle which can be used to force a re-render of the associated /// function component. -#[derive(Clone)] -pub struct UseForceUpdate { - trigger: ReRender, -} - -impl fmt::Debug for UseForceUpdate { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("UseForceUpdate").finish() - } -} - -impl UseForceUpdate { - /// Trigger an unconditional re-render of the associated function component - pub fn force_update(&self) { - (self.trigger)() - } -} - -#[cfg(feature = "nightly")] -mod feat_nightly { - use super::*; - - impl FnOnce<()> for UseForceUpdate { - type Output = (); - - extern "rust-call" fn call_once(self, _args: ()) -> Self::Output { - self.force_update() - } - } - - impl FnMut<()> for UseForceUpdate { - extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output { - self.force_update() - } - } - - impl Fn<()> for UseForceUpdate { - extern "rust-call" fn call(&self, _args: ()) -> Self::Output { - self.force_update() - } - } -} +type UseForceUpdateHandle = ReRender; /// This hook is used to manually force a function component to re-render. /// @@ -96,30 +53,16 @@ mod feat_nightly { /// /// [`use_state`]: super::use_state() /// [`use_reducer`]: super::use_reducer() -pub fn use_force_update() -> impl Hook { +pub fn use_force_update() -> impl Hook { struct UseRerenderHook; impl Hook for UseRerenderHook { - type Output = UseForceUpdate; + type Output = UseForceUpdateHandle; fn run(self, ctx: &mut HookContext) -> Self::Output { - UseForceUpdate { - trigger: ctx.re_render.clone(), - } + ctx.re_render.clone() } } UseRerenderHook } - -#[cfg(all(test, feature = "nightly"))] -mod nightly_test { - use yew::prelude::*; - - #[function_component] - fn ManuallyUpdatedDate() -> Html { - let trigger = use_force_update(); - let _ = move || trigger(); - html! {} - } -} From 16a9008a22133a3c2034868b5027da223ce63a2e Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Tue, 21 Jun 2022 00:52:04 +0500 Subject: [PATCH 07/10] Manually specify clippy features --- .github/workflows/main-checks.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main-checks.yml b/.github/workflows/main-checks.yml index 434d9047ee8..e4b3445e237 100644 --- a/.github/workflows/main-checks.yml +++ b/.github/workflows/main-checks.yml @@ -25,7 +25,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: clippy - args: --all-targets --all-features -- -D warnings + args: --all-targets --features "csr,ssr,hydration" -- -D warnings - name: Lint feature soundness run: | @@ -33,7 +33,7 @@ jobs: cargo clippy --features=ssr -- --deny=warnings cargo clippy --features=csr -- --deny=warnings cargo clippy --features=hydration -- --deny=warnings - cargo clippy --all-features --all-targets -- --deny=warnings + cargo clippy --features "csr,ssr,hydration,tokio" --all-targets -- --deny=warnings working-directory: packages/yew @@ -55,7 +55,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: clippy - args: --all-targets --all-features --release -- -D warnings + args: --all-targets --features "csr,ssr,hydration" --release -- -D warnings - name: Lint feature soundness run: | @@ -63,7 +63,7 @@ jobs: cargo clippy --release --features=ssr -- --deny=warnings cargo clippy --release --features=csr -- --deny=warnings cargo clippy --release --features=hydration -- --deny=warnings - cargo clippy --release --all-features --all-targets -- --deny=warnings + cargo clippy --release --features "csr,ssr,hydration,tokio" --all-targets -- --deny=warnings working-directory: packages/yew spell_check: From 8ffeb57b982f29c62aabbfe3429786a7b6b9bbd5 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Fri, 24 Jun 2022 19:01:14 +0500 Subject: [PATCH 08/10] Revert "Simplify UseForceUpdateHandle" This reverts commit 761dbb0f8bb7c280054d55dcc724f08604ee4ece. --- .../src/functional/hooks/use_force_update.rs | 65 +++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index f428c09491b..ef127f81917 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -1,9 +1,52 @@ +use std::fmt; + use super::{Hook, HookContext}; use crate::functional::ReRender; /// A handle which can be used to force a re-render of the associated /// function component. -type UseForceUpdateHandle = ReRender; +#[derive(Clone)] +pub struct UseForceUpdate { + trigger: ReRender, +} + +impl fmt::Debug for UseForceUpdate { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("UseForceUpdate").finish() + } +} + +impl UseForceUpdate { + /// Trigger an unconditional re-render of the associated function component + pub fn force_update(&self) { + (self.trigger)() + } +} + +#[cfg(feature = "nightly")] +mod feat_nightly { + use super::*; + + impl FnOnce<()> for UseForceUpdate { + type Output = (); + + extern "rust-call" fn call_once(self, _args: ()) -> Self::Output { + self.force_update() + } + } + + impl FnMut<()> for UseForceUpdate { + extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output { + self.force_update() + } + } + + impl Fn<()> for UseForceUpdate { + extern "rust-call" fn call(&self, _args: ()) -> Self::Output { + self.force_update() + } + } +} /// This hook is used to manually force a function component to re-render. /// @@ -53,16 +96,30 @@ type UseForceUpdateHandle = ReRender; /// /// [`use_state`]: super::use_state() /// [`use_reducer`]: super::use_reducer() -pub fn use_force_update() -> impl Hook { +pub fn use_force_update() -> impl Hook { struct UseRerenderHook; impl Hook for UseRerenderHook { - type Output = UseForceUpdateHandle; + type Output = UseForceUpdate; fn run(self, ctx: &mut HookContext) -> Self::Output { - ctx.re_render.clone() + UseForceUpdate { + trigger: ctx.re_render.clone(), + } } } UseRerenderHook } + +#[cfg(all(test, feature = "nightly"))] +mod nightly_test { + use yew::prelude::*; + + #[function_component] + fn ManuallyUpdatedDate() -> Html { + let trigger = use_force_update(); + let _ = move || trigger(); + html! {} + } +} From 17f37c0088706506e15e5cd7e797f4f170d3a7a0 Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Fri, 24 Jun 2022 19:02:02 +0500 Subject: [PATCH 09/10] `UseForceUpdateHandle` --- .../src/functional/hooks/use_force_update.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index ef127f81917..c467f60ceb9 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -6,17 +6,17 @@ use crate::functional::ReRender; /// A handle which can be used to force a re-render of the associated /// function component. #[derive(Clone)] -pub struct UseForceUpdate { +pub struct UseForceUpdateHandle { trigger: ReRender, } -impl fmt::Debug for UseForceUpdate { +impl fmt::Debug for UseForceUpdateHandle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("UseForceUpdate").finish() } } -impl UseForceUpdate { +impl UseForceUpdateHandle { /// Trigger an unconditional re-render of the associated function component pub fn force_update(&self) { (self.trigger)() @@ -27,7 +27,7 @@ impl UseForceUpdate { mod feat_nightly { use super::*; - impl FnOnce<()> for UseForceUpdate { + impl FnOnce<()> for UseForceUpdateHandle { type Output = (); extern "rust-call" fn call_once(self, _args: ()) -> Self::Output { @@ -35,13 +35,13 @@ mod feat_nightly { } } - impl FnMut<()> for UseForceUpdate { + impl FnMut<()> for UseForceUpdateHandle { extern "rust-call" fn call_mut(&mut self, _args: ()) -> Self::Output { self.force_update() } } - impl Fn<()> for UseForceUpdate { + impl Fn<()> for UseForceUpdateHandle { extern "rust-call" fn call(&self, _args: ()) -> Self::Output { self.force_update() } @@ -96,14 +96,14 @@ mod feat_nightly { /// /// [`use_state`]: super::use_state() /// [`use_reducer`]: super::use_reducer() -pub fn use_force_update() -> impl Hook { +pub fn use_force_update() -> impl Hook { struct UseRerenderHook; impl Hook for UseRerenderHook { - type Output = UseForceUpdate; + type Output = UseForceUpdateHandle; fn run(self, ctx: &mut HookContext) -> Self::Output { - UseForceUpdate { + UseForceUpdateHandle { trigger: ctx.re_render.clone(), } } From 0b3c9673506d3130d5a43009364ed43f7a80604d Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Fri, 24 Jun 2022 19:03:36 +0500 Subject: [PATCH 10/10] fmt --- packages/yew/src/functional/hooks/use_force_update.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yew/src/functional/hooks/use_force_update.rs b/packages/yew/src/functional/hooks/use_force_update.rs index c467f60ceb9..417273a015b 100644 --- a/packages/yew/src/functional/hooks/use_force_update.rs +++ b/packages/yew/src/functional/hooks/use_force_update.rs @@ -96,7 +96,7 @@ mod feat_nightly { /// /// [`use_state`]: super::use_state() /// [`use_reducer`]: super::use_reducer() -pub fn use_force_update() -> impl Hook { +pub fn use_force_update() -> impl Hook { struct UseRerenderHook; impl Hook for UseRerenderHook {