yew_hooks/hooks/
use_default.rs

1use std::ops::Deref;
2use std::rc::Rc;
3
4use yew::prelude::*;
5
6/// State handle for the [`use_default`] hook.
7pub struct UseDefaultHandle<T> {
8    inner: UseStateHandle<Option<T>>,
9    default: Rc<T>,
10}
11
12impl<T> UseDefaultHandle<T>
13where
14    T: 'static,
15{
16    /// Replaces the value.
17    pub fn set(&self, value: Option<T>) {
18        self.inner.set(value);
19    }
20}
21
22impl<T> Deref for UseDefaultHandle<T> {
23    type Target = T;
24
25    fn deref(&self) -> &Self::Target {
26        let value = &(*self.inner);
27        value.as_ref().unwrap_or_else(|| self.default.as_ref())
28    }
29}
30
31impl<T> Clone for UseDefaultHandle<T> {
32    fn clone(&self) -> Self {
33        Self {
34            inner: self.inner.clone(),
35            default: self.default.clone(),
36        }
37    }
38}
39
40impl<T> PartialEq for UseDefaultHandle<T>
41where
42    T: PartialEq,
43{
44    fn eq(&self, other: &Self) -> bool {
45        *self.inner == *other.inner
46    }
47}
48
49/// A state hook that returns the default value when state is None.
50///
51/// # Example
52///
53/// ```rust
54/// # use yew::prelude::*;
55/// #
56/// use yew_hooks::prelude::*;
57///
58/// #[function_component(UseDefault)]
59/// fn default() -> Html {
60///     let state = use_default(|| None, "Hello(default)".to_string());
61///
62///     let onclick = {
63///         let state = state.clone();
64///         Callback::from(move |_| {
65///             state.set(Some("World!".to_string()));
66///         })
67///     };
68///
69///     let onclear = {
70///         let state = state.clone();
71///         Callback::from(move |_| {
72///             state.set(None);
73///         })
74///     };
75///     
76///     html! {
77///         <>
78///             <button {onclick}>{ "Set to World!" }</button>
79///             <button onclick={onclear}>{ "Clear" }</button>
80///             <b>{ "Current value: " }</b>
81///             { &*state }
82///         </>
83///     }
84/// }
85/// ```
86#[hook]
87pub fn use_default<T, F>(init_fn: F, default: T) -> UseDefaultHandle<T>
88where
89    T: 'static,
90    F: FnOnce() -> Option<T>,
91{
92    let inner = use_state(init_fn);
93    let default = use_memo((), |_| default);
94
95    UseDefaultHandle { inner, default }
96}