use std::fmt;
use std::ops::Deref;
use std::rc::Rc;
use yew::prelude::*;
enum CounterAction {
Increase,
IncreaseBy(i32),
Decrease,
DecreaseBy(i32),
Set(i32),
Reset,
}
struct UseCounterReducer {
value: i32,
default: i32,
}
impl Reducible for UseCounterReducer {
type Action = CounterAction;
fn reduce(self: Rc<Self>, action: Self::Action) -> Rc<Self> {
let next_value = match action {
CounterAction::Increase => self.value + 1,
CounterAction::IncreaseBy(delta) => self.value + delta,
CounterAction::Decrease => self.value - 1,
CounterAction::DecreaseBy(delta) => self.value - delta,
CounterAction::Set(value) => value,
CounterAction::Reset => self.default,
};
Self {
value: next_value,
default: self.default,
}
.into()
}
}
impl PartialEq for UseCounterReducer {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
pub struct UseCounterHandle {
inner: UseReducerHandle<UseCounterReducer>,
}
impl UseCounterHandle {
pub fn increase(&self) {
self.inner.dispatch(CounterAction::Increase);
}
pub fn increase_by(&self, delta: i32) {
self.inner.dispatch(CounterAction::IncreaseBy(delta));
}
pub fn decrease(&self) {
self.inner.dispatch(CounterAction::Decrease);
}
pub fn decrease_by(&self, delta: i32) {
self.inner.dispatch(CounterAction::DecreaseBy(delta));
}
pub fn set(&self, value: i32) {
self.inner.dispatch(CounterAction::Set(value));
}
pub fn reset(&self) {
self.inner.dispatch(CounterAction::Reset);
}
}
impl fmt::Debug for UseCounterHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("UseCounterHandle")
.field("value", &format!("{:?}", self.inner.value))
.field("default", &format!("{:?}", self.inner.default))
.finish()
}
}
impl Deref for UseCounterHandle {
type Target = i32;
fn deref(&self) -> &Self::Target {
&self.inner.value
}
}
impl Clone for UseCounterHandle {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl PartialEq for UseCounterHandle {
fn eq(&self, other: &Self) -> bool {
*self.inner == *other.inner
}
}
#[hook]
pub fn use_counter(default: i32) -> UseCounterHandle {
let inner = use_reducer(move || UseCounterReducer {
value: default,
default,
});
UseCounterHandle { inner }
}