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}