From ed05abc19652bccec80ba144946b8712be01c949 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Mon, 7 Aug 2023 18:00:17 -0700 Subject: [PATCH] document remaining methods in the signal crate --- packages/signals/src/impls.rs | 3 ++ packages/signals/src/rt.rs | 10 +++++++ packages/signals/src/signal.rs | 53 ++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/packages/signals/src/impls.rs b/packages/signals/src/impls.rs index 4e81a5a27..6427c2e2b 100644 --- a/packages/signals/src/impls.rs +++ b/packages/signals/src/impls.rs @@ -37,6 +37,7 @@ macro_rules! read_impls { } impl $ty> { + /// Read a value from the inner vector. pub fn get(&self, index: usize) -> Option> { Ref::filter_map(self.read(), |v| v.get(index)).ok() } @@ -236,12 +237,14 @@ impl IntoIterator for CopyValue> { } impl CopyValue> { + /// Write to an element in the inner vector. pub fn get_mut(&self, index: usize) -> Option> { RefMut::filter_map(self.write(), |v| v.get_mut(index)).ok() } } impl CopyValue> { + /// Deref the inner value mutably. pub fn as_mut(&self) -> Option> { RefMut::filter_map(self.write(), |v| v.as_mut()).ok() } diff --git a/packages/signals/src/rt.rs b/packages/signals/src/rt.rs index dc1c4a66f..685a77204 100644 --- a/packages/signals/src/rt.rs +++ b/packages/signals/src/rt.rs @@ -61,6 +61,7 @@ impl CopyValue { } } + /// Create a new CopyValue. The value will be stored in the given scope. When the specified scope is dropped, the value will be dropped. pub fn new_in_scope(value: T, scope: ScopeId) -> Self { let owner = owner_in_scope(scope); @@ -79,35 +80,43 @@ impl CopyValue { } } + /// Get the scope this value was created in. pub fn origin_scope(&self) -> ScopeId { self.origin_scope } + /// Try to read the value. If the value has been dropped, this will return None. pub fn try_read(&self) -> Option> { self.value.try_read() } + /// Read the value. If the value has been dropped, this will panic. pub fn read(&self) -> Ref<'_, T> { self.value.read() } + /// Try to write the value. If the value has been dropped, this will return None. pub fn try_write(&self) -> Option> { self.value.try_write() } + /// Write the value. If the value has been dropped, this will panic. pub fn write(&self) -> RefMut<'_, T> { self.value.write() } + /// Set the value. If the value has been dropped, this will panic. pub fn set(&mut self, value: T) { *self.write() = value; } + /// Run a function with a reference to the value. If the value has been dropped, this will panic. pub fn with(&self, f: impl FnOnce(&T) -> O) -> O { let write = self.read(); f(&*write) } + /// Run a function with a mutable reference to the value. If the value has been dropped, this will panic. pub fn with_mut(&self, f: impl FnOnce(&mut T) -> O) -> O { let mut write = self.write(); f(&mut *write) @@ -115,6 +124,7 @@ impl CopyValue { } impl CopyValue { + /// Get the value. If the value has been dropped, this will panic. pub fn value(&self) -> T { self.read().clone() } diff --git a/packages/signals/src/signal.rs b/packages/signals/src/signal.rs index 8d2275b41..2bac8e1ea 100644 --- a/packages/signals/src/signal.rs +++ b/packages/signals/src/signal.rs @@ -81,11 +81,43 @@ pub(crate) struct SignalData { pub(crate) value: T, } +/// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking. +/// +/// ```rust +/// use dioxus::prelude::*; +/// use dioxus_signals::*; +/// +/// fn App(cx: Scope) -> Element { +/// let mut count = use_signal(cx, || 0); +/// +/// // Because signals have automatic dependency tracking, if you never read them in a component, that component will not be re-rended when the signal is updated. +/// // The app component will never be rerendered in this example. +/// render! { Child { state: count } } +/// } +/// +/// #[inline_props] +/// fn Child(cx: Scope, state: Signal) -> Element { +/// let state = *state; +/// +/// use_future!(cx, |()| async move { +/// // Because the signal is a Copy type, we can use it in an async block without cloning it. +/// *state.write() += 1; +/// }); +/// +/// render! { +/// button { +/// onclick: move |_| *state.write() += 1, +/// "{state}" +/// } +/// } +/// } +/// ``` pub struct Signal { pub(crate) inner: CopyValue>, } impl Signal { + /// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking. pub fn new(value: T) -> Self { Self { inner: CopyValue::new(SignalData { @@ -97,10 +129,13 @@ impl Signal { } } + /// Get the scope the signal was created in. pub fn origin_scope(&self) -> ScopeId { self.inner.origin_scope() } + /// Get the current value of the signal. This will subscribe the current scope to the signal. + /// If the signal has been dropped, this will panic. pub fn read(&self) -> Ref { let inner = self.inner.read(); if let Some(effect) = Effect::current() { @@ -128,6 +163,8 @@ impl Signal { Ref::map(inner, |v| &v.value) } + /// Get a mutable reference to the signal's value. + /// If the signal has been dropped, this will panic. pub fn write(&self) -> Write<'_, T> { let inner = self.inner.write(); let borrow = RefMut::map(inner, |v| &mut v.value); @@ -165,15 +202,20 @@ impl Signal { } } + /// Set the value of the signal. This will trigger an update on all subscribers. pub fn set(&self, value: T) { *self.write() = value; } + /// Run a closure with a reference to the signal's value. + /// If the signal has been dropped, this will panic. pub fn with(&self, f: impl FnOnce(&T) -> O) -> O { let write = self.read(); f(&*write) } + /// Run a closure with a mutable reference to the signal's value. + /// If the signal has been dropped, this will panic. pub fn with_mut(&self, f: impl FnOnce(&mut T) -> O) -> O { let mut write = self.write(); f(&mut *write) @@ -181,6 +223,8 @@ impl Signal { } impl Signal { + /// Get the current value of the signal. This will subscribe the current scope to the signal. + /// If the signal has been dropped, this will panic. pub fn value(&self) -> T { self.read().clone() } @@ -202,12 +246,14 @@ impl Drop for SignalSubscriberDrop { } } +/// A mutable reference to a signal's value. pub struct Write<'a, T: 'static, I: 'static = T> { write: RefMut<'a, T>, signal: SignalSubscriberDrop, } impl<'a, T: 'static, I: 'static> Write<'a, T, I> { + /// Map the mutable reference to the signal's value to a new type. pub fn map(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write<'a, O, I> { let Self { write, signal } = myself; Write { @@ -216,6 +262,7 @@ impl<'a, T: 'static, I: 'static> Write<'a, T, I> { } } + /// Try to map the mutable reference to the signal's value to a new type pub fn filter_map( myself: Self, f: impl FnOnce(&mut T) -> Option<&mut O>, @@ -243,29 +290,35 @@ impl DerefMut for Write<'_, T> { } } +/// A signal that can only be read from. pub struct ReadOnlySignal { inner: Signal, } impl ReadOnlySignal { + /// Create a new read-only signal. pub fn new(signal: Signal) -> Self { Self { inner: signal } } + /// Get the scope that the signal was created in. pub fn origin_scope(&self) -> ScopeId { self.inner.origin_scope() } + /// Get the current value of the signal. This will subscribe the current scope to the signal. pub fn read(&self) -> Ref { self.inner.read() } + /// Run a closure with a reference to the signal's value. pub fn with(&self, f: impl FnOnce(&T) -> O) -> O { self.inner.with(f) } } impl ReadOnlySignal { + /// Get the current value of the signal. This will subscribe the current scope to the signal. pub fn value(&self) -> T { self.read().clone() }