document remaining methods in the signal crate

This commit is contained in:
Evan Almloff committed 2023-08-07 18:00:17 -07:00
1 parent 0c17bdb737
commit ed05abc196
3 files changed
+66

No files matched your search

+3
View File
@@ -37,6 +37,7 @@ macro_rules! read_impls {
} }
impl<T: 'static> $ty<Vec<T>> { impl<T: 'static> $ty<Vec<T>> {
/// Read a value from the inner vector.
pub fn get(&self, index: usize) -> Option<Ref<'_, T>> { pub fn get(&self, index: usize) -> Option<Ref<'_, T>> {
Ref::filter_map(self.read(), |v| v.get(index)).ok() Ref::filter_map(self.read(), |v| v.get(index)).ok()
} }
@@ -236,12 +237,14 @@ impl<T: Clone + 'static> IntoIterator for CopyValue<Vec<T>> {
} }
impl<T: 'static> CopyValue<Vec<T>> { impl<T: 'static> CopyValue<Vec<T>> {
/// Write to an element in the inner vector.
pub fn get_mut(&self, index: usize) -> Option<RefMut<'_, T>> { pub fn get_mut(&self, index: usize) -> Option<RefMut<'_, T>> {
RefMut::filter_map(self.write(), |v| v.get_mut(index)).ok() RefMut::filter_map(self.write(), |v| v.get_mut(index)).ok()
} }
} }
impl<T: 'static> CopyValue<Option<T>> { impl<T: 'static> CopyValue<Option<T>> {
/// Deref the inner value mutably.
pub fn as_mut(&self) -> Option<RefMut<'_, T>> { pub fn as_mut(&self) -> Option<RefMut<'_, T>> {
RefMut::filter_map(self.write(), |v| v.as_mut()).ok() RefMut::filter_map(self.write(), |v| v.as_mut()).ok()
} }
+10
View File
@@ -61,6 +61,7 @@ impl<T: 'static> CopyValue<T> {
} }
} }
/// 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 { pub fn new_in_scope(value: T, scope: ScopeId) -> Self {
let owner = owner_in_scope(scope); let owner = owner_in_scope(scope);
@@ -79,35 +80,43 @@ impl<T: 'static> CopyValue<T> {
} }
} }
/// Get the scope this value was created in.
pub fn origin_scope(&self) -> ScopeId { pub fn origin_scope(&self) -> ScopeId {
self.origin_scope self.origin_scope
} }
/// Try to read the value. If the value has been dropped, this will return None.
pub fn try_read(&self) -> Option<Ref<'_, T>> { pub fn try_read(&self) -> Option<Ref<'_, T>> {
self.value.try_read() self.value.try_read()
} }
/// Read the value. If the value has been dropped, this will panic.
pub fn read(&self) -> Ref<'_, T> { pub fn read(&self) -> Ref<'_, T> {
self.value.read() self.value.read()
} }
/// Try to write the value. If the value has been dropped, this will return None.
pub fn try_write(&self) -> Option<RefMut<'_, T>> { pub fn try_write(&self) -> Option<RefMut<'_, T>> {
self.value.try_write() self.value.try_write()
} }
/// Write the value. If the value has been dropped, this will panic.
pub fn write(&self) -> RefMut<'_, T> { pub fn write(&self) -> RefMut<'_, T> {
self.value.write() self.value.write()
} }
/// Set the value. If the value has been dropped, this will panic.
pub fn set(&mut self, value: T) { pub fn set(&mut self, value: T) {
*self.write() = value; *self.write() = value;
} }
/// Run a function with a reference to the value. If the value has been dropped, this will panic.
pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O { pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
let write = self.read(); let write = self.read();
f(&*write) 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<O>(&self, f: impl FnOnce(&mut T) -> O) -> O { pub fn with_mut<O>(&self, f: impl FnOnce(&mut T) -> O) -> O {
let mut write = self.write(); let mut write = self.write();
f(&mut *write) f(&mut *write)
@@ -115,6 +124,7 @@ impl<T: 'static> CopyValue<T> {
} }
impl<T: Clone + 'static> CopyValue<T> { impl<T: Clone + 'static> CopyValue<T> {
/// Get the value. If the value has been dropped, this will panic.
pub fn value(&self) -> T { pub fn value(&self) -> T {
self.read().clone() self.read().clone()
} }
+53
View File
@@ -81,11 +81,43 @@ pub(crate) struct SignalData<T> {
pub(crate) value: T, 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<u32>) -> 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<T: 'static> { pub struct Signal<T: 'static> {
pub(crate) inner: CopyValue<SignalData<T>>, pub(crate) inner: CopyValue<SignalData<T>>,
} }
impl<T: 'static> Signal<T> { impl<T: 'static> Signal<T> {
/// Creates a new Signal. Signals are a Copy state management solution with automatic dependency tracking.
pub fn new(value: T) -> Self { pub fn new(value: T) -> Self {
Self { Self {
inner: CopyValue::new(SignalData { inner: CopyValue::new(SignalData {
@@ -97,10 +129,13 @@ impl<T: 'static> Signal<T> {
} }
} }
/// Get the scope the signal was created in.
pub fn origin_scope(&self) -> ScopeId { pub fn origin_scope(&self) -> ScopeId {
self.inner.origin_scope() 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<T> { pub fn read(&self) -> Ref<T> {
let inner = self.inner.read(); let inner = self.inner.read();
if let Some(effect) = Effect::current() { if let Some(effect) = Effect::current() {
@@ -128,6 +163,8 @@ impl<T: 'static> Signal<T> {
Ref::map(inner, |v| &v.value) 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> { pub fn write(&self) -> Write<'_, T> {
let inner = self.inner.write(); let inner = self.inner.write();
let borrow = RefMut::map(inner, |v| &mut v.value); let borrow = RefMut::map(inner, |v| &mut v.value);
@@ -165,15 +202,20 @@ impl<T: 'static> Signal<T> {
} }
} }
/// Set the value of the signal. This will trigger an update on all subscribers.
pub fn set(&self, value: T) { pub fn set(&self, value: T) {
*self.write() = value; *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<O>(&self, f: impl FnOnce(&T) -> O) -> O { pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
let write = self.read(); let write = self.read();
f(&*write) 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<O>(&self, f: impl FnOnce(&mut T) -> O) -> O { pub fn with_mut<O>(&self, f: impl FnOnce(&mut T) -> O) -> O {
let mut write = self.write(); let mut write = self.write();
f(&mut *write) f(&mut *write)
@@ -181,6 +223,8 @@ impl<T: 'static> Signal<T> {
} }
impl<T: Clone + 'static> Signal<T> { impl<T: Clone + 'static> Signal<T> {
/// 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 { pub fn value(&self) -> T {
self.read().clone() self.read().clone()
} }
@@ -202,12 +246,14 @@ impl<T: 'static> Drop for SignalSubscriberDrop<T> {
} }
} }
/// A mutable reference to a signal's value.
pub struct Write<'a, T: 'static, I: 'static = T> { pub struct Write<'a, T: 'static, I: 'static = T> {
write: RefMut<'a, T>, write: RefMut<'a, T>,
signal: SignalSubscriberDrop<I>, signal: SignalSubscriberDrop<I>,
} }
impl<'a, T: 'static, I: 'static> Write<'a, T, I> { 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<O>(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write<'a, O, I> { pub fn map<O>(myself: Self, f: impl FnOnce(&mut T) -> &mut O) -> Write<'a, O, I> {
let Self { write, signal } = myself; let Self { write, signal } = myself;
Write { 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<O>( pub fn filter_map<O>(
myself: Self, myself: Self,
f: impl FnOnce(&mut T) -> Option<&mut O>, f: impl FnOnce(&mut T) -> Option<&mut O>,
@@ -243,29 +290,35 @@ impl<T> DerefMut for Write<'_, T> {
} }
} }
/// A signal that can only be read from.
pub struct ReadOnlySignal<T: 'static> { pub struct ReadOnlySignal<T: 'static> {
inner: Signal<T>, inner: Signal<T>,
} }
impl<T: 'static> ReadOnlySignal<T> { impl<T: 'static> ReadOnlySignal<T> {
/// Create a new read-only signal.
pub fn new(signal: Signal<T>) -> Self { pub fn new(signal: Signal<T>) -> Self {
Self { inner: signal } Self { inner: signal }
} }
/// Get the scope that the signal was created in.
pub fn origin_scope(&self) -> ScopeId { pub fn origin_scope(&self) -> ScopeId {
self.inner.origin_scope() 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<T> { pub fn read(&self) -> Ref<T> {
self.inner.read() self.inner.read()
} }
/// Run a closure with a reference to the signal's value.
pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O { pub fn with<O>(&self, f: impl FnOnce(&T) -> O) -> O {
self.inner.with(f) self.inner.with(f)
} }
} }
impl<T: Clone + 'static> ReadOnlySignal<T> { impl<T: Clone + 'static> ReadOnlySignal<T> {
/// Get the current value of the signal. This will subscribe the current scope to the signal.
pub fn value(&self) -> T { pub fn value(&self) -> T {
self.read().clone() self.read().clone()
} }