reactive_graph/signal.rs
1//! Reactive primitives for root values that can be changed, notifying other nodes in the reactive
2//! graph.
3
4mod arc_read;
5mod arc_rw;
6mod arc_trigger;
7mod arc_write;
8pub mod guards;
9mod mapped;
10mod read;
11mod rw;
12mod subscriber_traits;
13mod trigger;
14mod write;
15
16use crate::owner::LocalStorage;
17pub use arc_read::*;
18pub use arc_rw::*;
19pub use arc_trigger::*;
20pub use arc_write::*;
21pub use mapped::*;
22pub use read::*;
23pub use rw::*;
24pub use trigger::*;
25pub use write::*;
26
27/// Creates a reference-counted signal.
28///
29/// A signal is a piece of data that may change over time, and notifies other
30/// code when it has changed. This is the atomic unit of reactivity, which begins all other
31/// processes of updating.
32///
33/// Takes the initial value as an argument, and returns a tuple containing an
34/// [`ArcReadSignal`] and an [`ArcWriteSignal`].
35///
36/// This returns reference-counted signals, which are `Clone` but not `Copy`. For arena-allocated
37/// `Copy` signals, use [`signal`].
38///
39/// ```
40/// # use reactive_graph::prelude::*;
41/// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
42/// let (count, set_count) = arc_signal(0);
43///
44/// // ✅ calling the getter clones and returns the value
45/// // this can be `count()` on nightly
46/// assert_eq!(count.get(), 0);
47///
48/// // ✅ calling the setter sets the value
49/// // this can be `set_count(1)` on nightly
50/// set_count.set(1);
51/// assert_eq!(count.get(), 1);
52///
53/// // ❌ you could call the getter within the setter
54/// // set_count.set(count.get() + 1);
55///
56/// // ✅ however it's more efficient to use .update() and mutate the value in place
57/// set_count.update(|count: &mut i32| *count += 1);
58/// assert_eq!(count.get(), 2);
59///
60/// // ✅ you can create "derived signals" with a Fn() -> T interface
61/// let double_count = move || count.get() * 2;
62/// set_count.set(0);
63/// assert_eq!(double_count(), 0);
64/// set_count.set(1);
65/// assert_eq!(double_count(), 2);
66/// ```
67#[inline(always)]
68#[track_caller]
69pub fn arc_signal<T>(value: T) -> (ArcReadSignal<T>, ArcWriteSignal<T>) {
70 ArcRwSignal::new(value).split()
71}
72
73/// Creates an arena-allocated signal, the basic reactive primitive.
74///
75/// A signal is a piece of data that may change over time, and notifies other
76/// code when it has changed. This is the atomic unit of reactivity, which begins all other
77/// processes of updating.
78///
79/// Takes the initial value as an argument, and returns a tuple containing a
80/// [`ReadSignal`] and a [`WriteSignal`].
81///
82/// This returns an arena-allocated signal, which is `Copy` and is disposed when its reactive
83/// [`Owner`](crate::owner::Owner) cleans up. For a reference-counted signal that lives
84/// as long as a reference to it is alive, see [`arc_signal`].
85/// ```
86/// # use reactive_graph::prelude::*;
87/// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
88/// let (count, set_count) = signal(0);
89///
90/// // ✅ calling the getter clones and returns the value
91/// // this can be `count()` on nightly
92/// assert_eq!(count.get(), 0);
93///
94/// // ✅ calling the setter sets the value
95/// // this can be `set_count(1)` on nightly
96/// set_count.set(1);
97/// assert_eq!(count.get(), 1);
98///
99/// // ❌ you could call the getter within the setter
100/// // set_count.set(count.get() + 1);
101///
102/// // ✅ however it's more efficient to use .update() and mutate the value in place
103/// set_count.update(|count: &mut i32| *count += 1);
104/// assert_eq!(count.get(), 2);
105///
106/// // ✅ you can create "derived signals" with a Fn() -> T interface
107/// let double_count = move || count.get() * 2; // signals are `Copy` so you can `move` them anywhere
108/// set_count.set(0);
109/// assert_eq!(double_count(), 0);
110/// set_count.set(1);
111/// assert_eq!(double_count(), 2);
112/// ```
113#[inline(always)]
114#[track_caller]
115pub fn signal<T: Send + Sync + 'static>(
116 value: T,
117) -> (ReadSignal<T>, WriteSignal<T>) {
118 let (r, w) = arc_signal(value);
119 (r.into(), w.into())
120}
121
122/// Creates an arena-allocated signal.
123///
124/// Unlike [`signal`], this does not require the value to be `Send + Sync`. Instead, it is stored
125/// on a local arena. Accessing either of the returned signals from another thread will panic.
126#[inline(always)]
127#[track_caller]
128pub fn signal_local<T: 'static>(
129 value: T,
130) -> (ReadSignal<T, LocalStorage>, WriteSignal<T, LocalStorage>) {
131 RwSignal::new_local(value).split()
132}
133
134/// Creates an arena-allocated signal, the basic reactive primitive.
135///
136/// A signal is a piece of data that may change over time, and notifies other
137/// code when it has changed. This is the atomic unit of reactivity, which begins all other
138/// processes of updating.
139///
140/// Takes the initial value as an argument, and returns a tuple containing a
141/// [`ReadSignal`] and a [`WriteSignal`].
142///
143/// This returns an arena-allocated signal, which is `Copy` and is disposed when its reactive
144/// [`Owner`](crate::owner::Owner) cleans up. For a reference-counted signal that lives
145/// as long as a reference to it is alive, see [`arc_signal`].
146/// ```
147/// # use reactive_graph::prelude::*;
148/// # use reactive_graph::signal::*; let owner = reactive_graph::owner::Owner::new(); owner.set();
149/// let (count, set_count) = create_signal(0);
150///
151/// // ✅ calling the getter clones and returns the value
152/// // this can be `count()` on nightly
153/// assert_eq!(count.get(), 0);
154///
155/// // ✅ calling the setter sets the value
156/// // this can be `set_count(1)` on nightly
157/// set_count.set(1);
158/// assert_eq!(count.get(), 1);
159///
160/// // ❌ you could call the getter within the setter
161/// // set_count.set(count.get() + 1);
162///
163/// // ✅ however it's more efficient to use .update() and mutate the value in place
164/// set_count.update(|count: &mut i32| *count += 1);
165/// assert_eq!(count.get(), 2);
166///
167/// // ✅ you can create "derived signals" with a Fn() -> T interface
168/// let double_count = move || count.get() * 2; // signals are `Copy` so you can `move` them anywhere
169/// set_count.set(0);
170/// assert_eq!(double_count(), 0);
171/// set_count.set(1);
172/// assert_eq!(double_count(), 2);
173/// ```
174#[inline(always)]
175#[track_caller]
176#[deprecated = "This function is being renamed to `signal()` to conform to \
177 Rust idioms."]
178pub fn create_signal<T: Send + Sync + 'static>(
179 value: T,
180) -> (ReadSignal<T>, WriteSignal<T>) {
181 signal(value)
182}
183
184/// Creates a reactive signal with the getter and setter unified in one value.
185#[inline(always)]
186#[track_caller]
187#[deprecated = "This function is being removed to conform to Rust idioms. \
188 Please use `RwSignal::new()` instead."]
189pub fn create_rw_signal<T: Send + Sync + 'static>(value: T) -> RwSignal<T> {
190 RwSignal::new(value)
191}
192
193/// A trigger is a data-less signal with the sole purpose of notifying other reactive code of a change.
194#[inline(always)]
195#[track_caller]
196#[deprecated = "This function is being removed to conform to Rust idioms. \
197 Please use `ArcTrigger::new()` instead."]
198pub fn create_trigger() -> ArcTrigger {
199 ArcTrigger::new()
200}