1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
use std::cell::{Ref, RefCell};
use std::collections::HashMap;
use std::hash::Hash;
use std::rc::Rc;
use yew::prelude::*;
use super::use_update;
/// State handle for the [`use_map`] hook.
pub struct UseMapHandle<K, V> {
inner: Rc<RefCell<HashMap<K, V>>>,
update: Rc<dyn Fn()>,
}
impl<K, V> UseMapHandle<K, V> {
/// Get immutable ref to the map.
///
/// # Panics
///
/// Panics if the value is currently mutably borrowed
pub fn current(&self) -> Ref<HashMap<K, V>> {
self.inner.borrow()
}
/// Set the hash map.
pub fn set(&self, map: HashMap<K, V>) {
*self.inner.borrow_mut() = map;
(self.update)();
}
/// Inserts a key-value pair into the map.
pub fn insert(&self, k: K, v: V) -> Option<V>
where
K: Eq + Hash,
{
let v = self.inner.borrow_mut().insert(k, v);
(self.update)();
v
}
/// Update key-value pair.
pub fn update(&self, k: &K, v: V)
where
K: Eq + Hash,
{
if let Some(value) = self.inner.borrow_mut().get_mut(k) {
*value = v;
}
(self.update)();
}
/// Removes a key from the map, returning the value at the key if the key was previously in the map.
pub fn remove(&self, k: &K) -> Option<V>
where
K: Eq + Hash,
{
let v = self.inner.borrow_mut().remove(k);
(self.update)();
v
}
/// Retains only the elements specified by the predicate.
pub fn retain<F>(&self, f: F)
where
K: Eq + Hash,
F: FnMut(&K, &mut V) -> bool,
{
self.inner.borrow_mut().retain(f);
(self.update)();
}
/// Clears the map, removing all key-value pairs. Keeps the allocated memory for reuse.
pub fn clear(&self) {
self.inner.borrow_mut().clear();
(self.update)();
}
}
impl<K, V> Clone for UseMapHandle<K, V> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
update: self.update.clone(),
}
}
}
impl<K, V> PartialEq for UseMapHandle<K, V>
where
K: Eq + Hash,
V: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
*self.inner == *other.inner
}
}
/// A hook that tracks a hash map and provides methods to modify it.
///
/// # Example
///
/// ```rust
/// # use std::collections::HashMap;
/// # use yew::prelude::*;
/// #
/// use yew_hooks::prelude::*;
///
/// #[function_component(UseMap)]
/// fn map() -> Html {
/// let map = use_map(HashMap::from([
/// ("Mercury", 0.4),
/// ("Venus", 0.7),
/// ("Earth", 1.0),
/// ("Mars", 1.5),
/// ]));
///
/// let onset = {
/// let map = map.clone();
/// Callback::from(move |_| map.set(HashMap::from([("Moon", 0.8), ("Earth", 1.0)])))
/// };
/// let oninsert = {
/// let map = map.clone();
/// Callback::from(move |_| {
/// let _ = map.insert("Jupiter", 2.1);
/// })
/// };
/// let onupdate = {
/// let map = map.clone();
/// Callback::from(move |_| map.update(&"Earth", 1.1))
/// };
/// let onremove = {
/// let map = map.clone();
/// Callback::from(move |_| {
/// let _ = map.remove(&"Moon");
/// })
/// };
/// let onretain = {
/// let map = map.clone();
/// Callback::from(move |_| map.retain(|_k, v| v > &mut 1.0))
/// };
/// let onclear = {
/// let map = map.clone();
/// Callback::from(move |_| map.clear())
/// };
///
/// html! {
/// <div>
/// <button onclick={onset}>{ "Set" }</button>
/// <button onclick={oninsert}>{ "Insert" }</button>
/// <button onclick={onupdate}>{ "Update" }</button>
/// <button onclick={onremove}>{ "Remove" }</button>
/// <button onclick={onretain}>{ "Retain" }</button>
/// <button onclick={onclear}>{ "Clear all" }</button>
/// <p>
/// <b>{ "Current value: " }</b>
/// </p>
/// {
/// for map.current().iter().map(|(k, v)| {
/// html! {
/// <p><b>{ k }</b> {": "} { v }</p>
/// }
/// })
/// }
/// </div>
/// }
/// }
/// ```
#[hook]
pub fn use_map<K, V>(initial_value: HashMap<K, V>) -> UseMapHandle<K, V>
where
K: 'static,
V: 'static,
{
let inner = use_mut_ref(|| initial_value);
let update = use_update();
UseMapHandle { inner, update }
}