yew_hooks/hooks/use_queue.rs
1use std::cell::{Ref, RefCell};
2use std::collections::VecDeque;
3use std::hash::Hash;
4use std::rc::Rc;
5
6use yew::prelude::*;
7
8use super::use_update;
9
10/// State handle for the [`use_queue`] hook.
11pub struct UseQueueHandle<T> {
12 inner: Rc<RefCell<VecDeque<T>>>,
13 update: Rc<dyn Fn()>,
14}
15
16impl<T> UseQueueHandle<T> {
17 /// Get immutable ref to the queue.
18 ///
19 /// # Panics
20 ///
21 /// Panics if the value is currently mutably borrowed
22 pub fn current(&self) -> Ref<VecDeque<T>> {
23 self.inner.borrow()
24 }
25
26 /// Set the queue.
27 pub fn set(&self, queue: VecDeque<T>) {
28 *self.inner.borrow_mut() = queue;
29 (self.update)();
30 }
31
32 /// Appends an element to the back of the queue.
33 pub fn push_back(&self, value: T)
34 where
35 T: Eq + Hash,
36 {
37 self.inner.borrow_mut().push_back(value);
38 (self.update)();
39 }
40
41 /// Removes the first element and returns it, or None if the queue is empty.
42 pub fn pop_front(&self) -> Option<T>
43 where
44 T: Eq + Hash,
45 {
46 let v = self.inner.borrow_mut().pop_front();
47 (self.update)();
48 v
49 }
50
51 /// Retains only the elements specified by the predicate.
52 pub fn retain<F>(&self, f: F)
53 where
54 T: Eq + Hash,
55 F: FnMut(&T) -> bool,
56 {
57 self.inner.borrow_mut().retain(f);
58 (self.update)();
59 }
60
61 /// Clears the queue, removing all values.
62 pub fn clear(&self) {
63 self.inner.borrow_mut().clear();
64 (self.update)();
65 }
66}
67
68impl<T> Clone for UseQueueHandle<T> {
69 fn clone(&self) -> Self {
70 Self {
71 inner: self.inner.clone(),
72 update: self.update.clone(),
73 }
74 }
75}
76
77impl<T> PartialEq for UseQueueHandle<T>
78where
79 T: Eq + Hash,
80{
81 fn eq(&self, other: &Self) -> bool {
82 *self.inner == *other.inner
83 }
84}
85
86/// A hook that tracks a queue and provides methods to modify it.
87///
88/// # Example
89///
90/// ```rust
91/// # use std::collections::VecDeque;
92/// # use yew::prelude::*;
93/// #
94/// use yew_hooks::prelude::*;
95///
96/// #[function_component(UseQueue)]
97/// fn queue() -> Html {
98/// let queue = use_queue(VecDeque::from(["Mercury", "Venus", "Earth", "Mars"]));
99///
100/// let onset = {
101/// let queue = queue.clone();
102/// Callback::from(move |_| queue.set(VecDeque::from(["Moon", "Earth"])))
103/// };
104/// let onpush_back = {
105/// let queue = queue.clone();
106/// Callback::from(move |_| {
107/// queue.push_back("Jupiter");
108/// })
109/// };
110/// let onpop_front = {
111/// let queue = queue.clone();
112/// Callback::from(move |_| {
113/// let _ = queue.pop_front();
114/// })
115/// };
116/// let onretain = {
117/// let queue = queue.clone();
118/// Callback::from(move |_| queue.retain(|v| v.contains('a')))
119/// };
120/// let onclear = {
121/// let queue = queue.clone();
122/// Callback::from(move |_| queue.clear())
123/// };
124///
125/// html! {
126/// <div>
127/// <button onclick={onset}>{ "Set" }</button>
128/// <button onclick={onpush_back}>{ "Push back" }</button>
129/// <button onclick={onpop_front}>{ "Pop front" }</button>
130/// <button onclick={onretain}>{ "Retain" }</button>
131/// <button onclick={onclear}>{ "Clear all" }</button>
132/// <p>
133/// <b>{ "Current value: " }</b>
134/// </p>
135/// {
136/// for queue.current().iter().map(|v| {
137/// html! {
138/// <p><b>{ v }</b></p>
139/// }
140/// })
141/// }
142/// </div>
143/// }
144/// }
145/// ```
146#[hook]
147pub fn use_queue<T>(initial_value: VecDeque<T>) -> UseQueueHandle<T>
148where
149 T: 'static,
150{
151 let inner = use_mut_ref(|| initial_value);
152 let update = use_update();
153
154 UseQueueHandle { inner, update }
155}