Skip to content

Commit

Permalink
Create use_state hook
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Sep 30, 2023
1 parent eacfc5d commit d463872
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 14 deletions.
18 changes: 5 additions & 13 deletions examples/ui.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
use std::cell::RefCell;
use viewbuilder::ui::{Scope, View};
use viewbuilder::view;

#[view]
fn button<'cx>(
cx: &'cx Scope,
count: &'cx RefCell<i32>,
label: &'static str,
mut on_click: impl FnMut(&mut i32) + 'cx,
) -> View<'cx> {
View::new()
.text(label)
.on_click(move || on_click(&mut *count.borrow_mut()))
fn button<'cx>(cx: &'cx Scope, label: &'static str, mut on_click: impl FnMut() + 'cx) -> View<'cx> {
View::new().text(label).on_click(move || on_click())
}

#[view]
fn app(cx: &Scope) -> View {
let count = cx.use_hook(|| RefCell::new(0));
let mut count = cx.use_state(|| 0);

View::new()
.text(count.borrow().to_string())
.component(|cx| button(cx, count, "Less", |c| *c -= 1))
.component(|cx| button(cx, count, "More", |c| *c += 1))
.component(move |cx| button(cx, "Less", move || count -= 1))
.component(move |cx| button(cx, "More", move || count += 1))
}

fn main() -> Result<(), viewbuilder::Error> {
Expand Down
2 changes: 2 additions & 0 deletions src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub use scope::Scope;
mod view;
pub use view::View;

mod state;

pub struct HandlerCell<'cx> {
f: Rc<RefCell<Option<Box<dyn FnMut()>>>>,
_marker: PhantomData<&'cx ()>,
Expand Down
6 changes: 5 additions & 1 deletion src/ui/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{
cell::{RefCell, UnsafeCell},
};

use super::View;
use super::{View, state::State};

#[derive(Default)]
pub struct Scope {
Expand All @@ -20,6 +20,10 @@ impl Scope {
f()
}

pub fn use_state<T: 'static>(&self, f: impl FnOnce() -> T) -> &State<T> {
self.use_hook(|| State::new(f()))
}

pub fn use_hook<T: 'static>(&self, f: impl FnOnce() -> T) -> &mut T {
let mut states = self.states.borrow_mut();

Expand Down
38 changes: 38 additions & 0 deletions src/ui/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::{
cell::{RefCell, Ref},
ops::{AddAssign, SubAssign, Deref},
rc::Rc,
};

#[derive(Clone)]
pub struct State<T> {
value: Rc<RefCell<T>>,
}

impl<T> State<T> {
pub(crate) fn new(value: T) -> Self {
Self { value: Rc::new(RefCell::new(value)) }
}

pub fn update(&self, f: impl FnOnce(&mut T)) {
f(&mut *self.value.borrow_mut())
}

pub fn borrow(&self) -> Ref<T> {
self.value.borrow()
}
}



impl<T: AddAssign> AddAssign<T> for &State<T> {
fn add_assign(&mut self, rhs: T) {
self.update(|val| *val += rhs)
}
}

impl<T: SubAssign> SubAssign<T> for &State<T> {
fn sub_assign(&mut self, rhs: T) {
self.update(|val| *val -= rhs)
}
}

0 comments on commit d463872

Please sign in to comment.