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}