yew_hooks/hooks/use_session_storage.rs
1use std::ops::Deref;
2use std::rc::Rc;
3
4use gloo::storage::{SessionStorage, Storage};
5use serde::{Deserialize, Serialize};
6use yew::prelude::*;
7
8/// State handle for the [`use_session_storage`] hook.
9pub struct UseSessionStorageHandle<T> {
10 inner: UseStateHandle<Option<T>>,
11 key: Rc<String>,
12}
13
14impl<T> UseSessionStorageHandle<T> {
15 /// Set a `value` for the specified key.
16 pub fn set(&self, value: T)
17 where
18 T: Serialize + Clone,
19 {
20 if SessionStorage::set(&*self.key, value.clone()).is_ok() {
21 self.inner.set(Some(value));
22 }
23 }
24
25 /// Delete a key and it's stored value.
26 pub fn delete(&self) {
27 SessionStorage::delete(&*self.key);
28 self.inner.set(None);
29 }
30}
31
32impl<T> Deref for UseSessionStorageHandle<T> {
33 type Target = Option<T>;
34
35 fn deref(&self) -> &Self::Target {
36 &self.inner
37 }
38}
39
40impl<T> Clone for UseSessionStorageHandle<T> {
41 fn clone(&self) -> Self {
42 Self {
43 inner: self.inner.clone(),
44 key: self.key.clone(),
45 }
46 }
47}
48
49impl<T> PartialEq for UseSessionStorageHandle<T>
50where
51 T: PartialEq,
52{
53 fn eq(&self, other: &Self) -> bool {
54 *self.inner == *other.inner
55 }
56}
57
58/// A side-effect hook that manages a single sessionStorage key.
59///
60/// # Example
61///
62/// ```rust
63/// # use yew::prelude::*;
64/// #
65/// use yew_hooks::prelude::*;
66///
67/// #[function_component(SessionStorage)]
68/// fn session_storage() -> Html {
69/// let storage = use_session_storage::<String>("foo".to_string());
70///
71/// let onclick = {
72/// let storage = storage.clone();
73/// Callback::from(move |_| storage.set("bar".to_string()))
74/// };
75/// let ondelete = {
76/// let storage = storage.clone();
77/// Callback::from(move |_| storage.delete())
78/// };
79///
80/// html! {
81/// <div>
82/// <button onclick={onclick}>{ "Set to bar" }</button>
83/// <button onclick={ondelete}>{ "Delete" }</button>
84/// <p>
85/// <b>{ "Current value: " }</b>
86/// {
87/// if let Some(value) = &*storage {
88/// html! { value }
89/// } else {
90/// html! {}
91/// }
92/// }
93/// </p>
94/// </div>
95/// }
96/// }
97/// ```
98#[hook]
99pub fn use_session_storage<T>(key: String) -> UseSessionStorageHandle<T>
100where
101 T: for<'de> Deserialize<'de> + 'static,
102{
103 let inner: UseStateHandle<Option<T>> =
104 use_state(|| SessionStorage::get(&key).unwrap_or_default());
105 let key = use_memo((), |_| key);
106
107 UseSessionStorageHandle { inner, key }
108}