From 439bc4e9e6f83c96aaba006b0976aa65ac33f1b9 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Fri, 19 Jan 2024 12:13:55 -0600 Subject: [PATCH] remove computed now that selectors exist --- packages/hooks/src/computed.rs | 214 --------------------------------- 1 file changed, 214 deletions(-) delete mode 100644 packages/hooks/src/computed.rs diff --git a/packages/hooks/src/computed.rs b/packages/hooks/src/computed.rs deleted file mode 100644 index 42421a3d3..000000000 --- a/packages/hooks/src/computed.rs +++ /dev/null @@ -1,214 +0,0 @@ -//! Tracked and computed state in Dioxus - -use dioxus_core::{ScopeId}; -use slab::Slab; -use std::{ - cell::{RefCell, RefMut}, - collections::HashSet, - ops::{Deref, DerefMut}, - rc::Rc, -}; - -/// Create a new tracked state. -/// Tracked state is state that can drive Selector state -/// -/// It will efficiently update any Selector state that is reading from it, but it is not readable on its own. -/// -/// ```rust -/// use dioxus::prelude::*; -/// -/// #[component] -/// fn Parent() -> Element { -/// let count = use_tracked_state(|| 0); -/// -/// rsx! { -/// Child { -/// count: count.clone(), -/// } -/// } -/// } -/// -/// #[component] -/// fn Child(count: Tracked) -> Element { -/// let less_than_five = use_selector(count, |count| *count < 5); -/// -/// rsx! { -/// "{less_than_five}" -/// } -/// } -/// ``` -#[must_use] -pub fn use_tracked_state(nit: impl FnOnce() -> T) -> &Tracked { - cx.use_hook(|| { - let init = init(); - Tracked::new(init) - }) -} - -/// Tracked state is state that can drive Selector state -/// -/// Tracked state will efficiently update any Selector state that is reading from it, but it is not readable on it's own. -#[derive(Clone)] -pub struct Tracked { - state: Rc>, - update_any: std::sync::Arc, - subscribers: SubscribedCallbacks, -} - -impl PartialEq for Tracked { - fn eq(&self, other: &Self) -> bool { - self.state == other.state - } -} - -impl Tracked { - /// Create a new tracked state - pub fn new(, state: I) -> Self { - let subscribers = std::rc::Rc::new(std::cell::RefCell::new(Slab::new())); - Self { - state: Rc::new(RefCell::new(state)), - subscribers, - update_any: cx.schedule_update_any(), - } - } - - /// Create a new Selector state from this tracked state - pub fn compute( - &self, - mut compute: impl FnMut(&I) -> O + 'static, - ) -> Selector { - let subscribers = Rc::new(RefCell::new(HashSet::new())); - let state = Rc::new(RefCell::new(compute(&self.state.borrow()))); - let update_any = self.update_any.clone(); - - Selector { - value: state.clone(), - subscribers: subscribers.clone(), - _tracker: Rc::new(self.track(move |input_state| { - let new = compute(input_state); - let different = { - let state = state.borrow(); - *state != new - }; - if different { - let mut state = state.borrow_mut(); - *state = new; - for id in subscribers.borrow().iter().copied() { - (update_any)(id); - } - } - })), - } - } - - pub(crate) fn track(&self, update: impl FnMut(&I) + 'static) -> Tracker { - let mut subscribers = self.subscribers.borrow_mut(); - let id = subscribers.insert(Box::new(update)); - Tracker { - subscribers: self.subscribers.clone(), - id, - } - } - - /// Write to the tracked state - pub fn write(&self) -> TrackedMut<'_, I> { - TrackedMut { - state: self.state.borrow_mut(), - subscribers: self.subscribers.clone(), - } - } -} - -/// A mutable reference to tracked state -pub struct TrackedMut<'a, I> { - state: RefMut<'a, I>, - subscribers: SubscribedCallbacks, -} - -impl<'a, I> Deref for TrackedMut<'a, I> { - type Target = I; - - fn deref(&self) -> &Self::Target { - &self.state - } -} - -impl<'a, I> DerefMut for TrackedMut<'a, I> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.state - } -} - -impl<'a, I> Drop for TrackedMut<'a, I> { - fn drop(&mut self) { - let state = self.state.deref(); - for (_, sub) in &mut *self.subscribers.borrow_mut() { - sub(state); - } - } -} - -type SubscribedCallbacks = std::rc::Rc>>>; - -pub(crate) struct Tracker { - subscribers: SubscribedCallbacks, - id: usize, -} - -impl Drop for Tracker { - fn drop(&mut self) { - let _ = self.subscribers.borrow_mut().remove(self.id); - } -} - -#[must_use = "Consider using the `use_effect` hook to rerun an effect whenever the tracked state changes if you don't need the result of the computation"] -pub fn use_selector - tracked: &Tracked, - init: impl FnMut(&I) -> O + 'static, -) -> O { - let selector = cx.use_hook(|| tracked.compute(init)); - selector.use_signal(cx) -} - -/// Selector state is state that is derived from tracked state -/// -/// Whenever the tracked state changes, the Selector state will be updated and any components reading from it will be rerun -#[derive(Clone)] -pub struct Selector { - _tracker: Rc>, - value: Rc>, - subscribers: Rc>>, -} - -impl PartialEq for Selector { - fn eq(&self, other: &Self) -> bool { - std::rc::Rc::ptr_eq(&self.value, &other.value) - } -} - -impl Selector { - /// Read the Selector state and subscribe to updates - pub fn use_signal(&self, ) -> T { - cx.use_hook(|| { - let id = cx.scope_id(); - self.subscribers.borrow_mut().insert(id); - - ComputedRead { - scope: cx.scope_id(), - subscribers: self.subscribers.clone(), - } - }); - self.value.borrow().clone() - } -} - -struct ComputedRead { - scope: ScopeId, - subscribers: std::rc::Rc>>, -} - -impl Drop for ComputedRead { - fn drop(&mut self) { - self.subscribers.borrow_mut().remove(&self.scope); - } -}