diff --git a/packages/yew/src/functional/hooks/use_state.rs b/packages/yew/src/functional/hooks/use_state.rs index bd6d5b116bf..727a6648801 100644 --- a/packages/yew/src/functional/hooks/use_state.rs +++ b/packages/yew/src/functional/hooks/use_state.rs @@ -75,10 +75,24 @@ impl fmt::Debug for UseStateHandle { } impl UseStateHandle { - /// Updates the value + /// Replaces the value + /// + /// *Always causes a rerender* pub fn set(&self, value: T) { (self.setter)(value) } + /// Replaces the value if it is different from previous value + /// + /// **Only available for value types that implement PartialEq trait** + pub fn set_if_neq(&self, value: T) + where + T: PartialEq, + { + if *self.value == value { + return; + } + self.set(value) + } } impl Deref for UseStateHandle { diff --git a/packages/yew/tests/use_state.rs b/packages/yew/tests/use_state.rs index d7430618c0f..c3de10416f8 100644 --- a/packages/yew/tests/use_state.rs +++ b/packages/yew/tests/use_state.rs @@ -79,3 +79,40 @@ fn multiple_use_state_setters() { let result = obtain_result(); assert_eq!(result.as_str(), "11"); } + +#[wasm_bindgen_test] +fn use_state_handle_set_neq_works() { + static mut RENDER_COUNT: usize = 0; + + struct UseStateFunction {} + + impl FunctionProvider for UseStateFunction { + type TProps = (); + + fn run(_: &Self::TProps) -> Html { + // No race conditions will be caused since its only used in one place + unsafe { + RENDER_COUNT += 1; + } + let counter = use_state(|| 0); + counter.set_if_neq(1); + + return html! { +
+ {"Test Output: "} +
{*counter}
+ {"\n"} +
+ }; + } + } + type UseComponent = FunctionComponent; + yew::start_app_in_element::( + yew::utils::document().get_element_by_id("output").unwrap(), + ); + let result = obtain_result(); + assert_eq!(result.as_str(), "1"); + unsafe { + assert_eq!(RENDER_COUNT, 2); + } +} diff --git a/website/docs/concepts/function-components/pre-defined-hooks.md b/website/docs/concepts/function-components/pre-defined-hooks.md index c1d699c4c3a..ec064db4f1f 100644 --- a/website/docs/concepts/function-components/pre-defined-hooks.md +++ b/website/docs/concepts/function-components/pre-defined-hooks.md @@ -7,7 +7,8 @@ description: "The pre-defined Hooks that Yew comes with " `use_state` is used to manage state in a function component. It returns a `UseState` object which `Deref`s to the current value -and provides a `set` method to update the value. +and provides `set` and `set_if_neq` methods to update the value. +Note that `set_if_neq` is only available if your value implements `PartialEq` trait. The hook takes a function as input which determines the initial state. This value remains up-to-date on subsequent renders.