From 2c54ff768569b5b6313bf47c8a5ab8288b2cb27b Mon Sep 17 00:00:00 2001 From: schvv31n Date: Thu, 28 Sep 2023 21:14:34 +0100 Subject: [PATCH] added (UseReducerHandle/UseStateHandle)::(get/into_inner) --- .../yew/src/functional/hooks/use_reducer.rs | 17 +++++++++++++++++ packages/yew/src/functional/hooks/use_state.rs | 17 +++++++++++++++++ packages/yew/src/suspense/hooks.rs | 4 ++-- packages/yew/tests/use_state.rs | 2 ++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/yew/src/functional/hooks/use_reducer.rs b/packages/yew/src/functional/hooks/use_reducer.rs index 7b01dce76cd..24cf2f0112c 100644 --- a/packages/yew/src/functional/hooks/use_reducer.rs +++ b/packages/yew/src/functional/hooks/use_reducer.rs @@ -39,6 +39,11 @@ impl UseReducerHandle where T: Reducible, { + /// Returns the inner value of the handle in an `Rc`. + pub fn get(&self) -> Rc { + self.value.clone() + } + /// Dispatch the given action to the reducer. pub fn dispatch(&self, value: T::Action) { (self.dispatch)(value) @@ -50,6 +55,18 @@ where dispatch: self.dispatch.clone(), } } + + /// Destrctures the handle into its 2 parts: + /// 0: the current data associated with the reducer; + /// 1: the dispatcher responsible for applying an action to the value. + pub fn into_inner(self) -> (Rc, UseReducerDispatcher) { + ( + self.value, + UseReducerDispatcher { + dispatch: self.dispatch, + }, + ) + } } impl Deref for UseReducerHandle diff --git a/packages/yew/src/functional/hooks/use_state.rs b/packages/yew/src/functional/hooks/use_state.rs index dc68aedc793..4993109e41e 100644 --- a/packages/yew/src/functional/hooks/use_state.rs +++ b/packages/yew/src/functional/hooks/use_state.rs @@ -1,10 +1,12 @@ use std::fmt; +use std::mem::transmute; use std::ops::Deref; use std::rc::Rc; use super::{use_reducer, use_reducer_eq, Reducible, UseReducerDispatcher, UseReducerHandle}; use crate::functional::hook; +#[repr(transparent)] struct UseStateReducer { value: T, } @@ -111,6 +113,12 @@ impl fmt::Debug for UseStateHandle { } impl UseStateHandle { + /// Returns the inner value of the handle. + pub fn get(&self) -> Rc { + // Safety: `UseStateReducer` is `repr(transparent)` and only contains `T` + unsafe { transmute(self.inner.get()) } + } + /// Replaces the value pub fn set(&self, value: T) { self.inner.dispatch(value) @@ -122,6 +130,15 @@ impl UseStateHandle { inner: self.inner.dispatcher(), } } + + /// Destructures the handle into its 2 parts: + /// 0: The current associated state; + /// 1: The setter responsible for changing the state on demand. + pub fn into_inner(self) -> (Rc, UseStateSetter) { + let (data, inner) = self.inner.into_inner(); + // Safety: check the `get` method above + (unsafe { transmute(data) }, UseStateSetter { inner }) + } } impl Deref for UseStateHandle { diff --git a/packages/yew/src/suspense/hooks.rs b/packages/yew/src/suspense/hooks.rs index b31a57663d6..7140d8b44d5 100644 --- a/packages/yew/src/suspense/hooks.rs +++ b/packages/yew/src/suspense/hooks.rs @@ -101,14 +101,14 @@ where use_memo_base( move |deps| { - let self_id = latest_id.get().wrapping_add(1); + let self_id = (*latest_id).get().wrapping_add(1); // As long as less than 2**32 futures are in flight wrapping_add is fine (*latest_id).set(self_id); let deps = Rc::new(deps); let task = f(deps.clone()); let suspension = Suspension::from_future(async move { let result = task.await; - if latest_id.get() == self_id { + if (*latest_id).get() == self_id { output.set(Some(result)); } }); diff --git a/packages/yew/tests/use_state.rs b/packages/yew/tests/use_state.rs index c48bc0f295d..ab333943763 100644 --- a/packages/yew/tests/use_state.rs +++ b/packages/yew/tests/use_state.rs @@ -2,6 +2,7 @@ mod common; +use std::rc::Rc; use std::time::Duration; use common::obtain_result; @@ -16,6 +17,7 @@ async fn use_state_works() { #[function_component(UseComponent)] fn use_state_comp() -> Html { let counter = use_state(|| 0); + assert_eq!(counter.get(), Rc::new(0)); if *counter < 5 { counter.set(*counter + 1) }