| Crates.io | reactivity |
| lib.rs | reactivity |
| version | 0.1.1 |
| created_at | 2025-05-13 15:08:15.611775+00 |
| updated_at | 2025-05-16 15:40:28.830045+00 |
| description | A lightweight library for reactive programming with signals in Rust. |
| homepage | https://github.com/dexermatters/reactivity |
| repository | https://github.com/dexermatters/reactivity |
| max_upload_size | |
| id | 1672063 |
| size | 46,026 |
A lightweight library for reactive programming with signals in Rust.
Reactivity is a Rust library that provides a flexible reactive programming system. It allows you to create signals that can depend on other signals, with automatic propagation of changes through your dependency graph.
reactivity::Signal for single-threaded contextsreactivity::sync::Signal for thread-safe, multi-threaded contextsAdd the following to your Cargo.toml:
[dependencies]
reactivity = "0.1.0"
use reactivity::Signal;
use reactivity::signal;
fn main() {
// Create a basic signal
let count = signal!(0);
// Create a derived signal that depends on count
let doubled = signal!([count] count * 2);
// Create another signal with a side effect
let message = signal!(<old_val, new_val> [count]
format!("The count is {}", count);
println!("Count changed from {} to {}!", old_val, new_val)
);
// Update the original signal
count.send(5);
// The changes have been automatically propagated
assert_eq!(count.get(), 5);
assert_eq!(doubled.get(), 10);
assert_eq!(message.get(), "The count is 5");
}
use std::thread;
use reactivity::sync::Signal;
use reactivity::signal;
fn main() {
// Create a thread-safe signal
let count = signal!(0);
// Create dependent signals
let doubled = signal!([count] count * 2);
// Clone for use in another thread
let count_clone = count.clone();
// Spawn a thread that updates the signal
let handle = thread::spawn(move || {
for i in 1..=5 {
count_clone.send(i);
thread::sleep(std::time::Duration::from_millis(100));
}
});
// Wait for thread to complete
handle.join().unwrap();
// Main thread can access the updated value
assert_eq!(doubled.get(), 10);
}
Signal<T>: For single-threaded contexts (uses Rc and RefCell internally)sync::Signal<T>: Thread-safe implementation (uses Arc and RwLock internally)// Single-threaded signal
use reactivity::Signal;
let x = Signal::new(42);
// Thread-safe signal
use reactivity::sync::Signal;
let y = Signal::new(42);
// Create dependent signals
let a = Signal::new(1);
let b = signal!([a] a * 2);
// Register dependency (b will update when a changes)
a.add_receiver(b);
The signal! macro provides a convenient way to create signals. The macro automatically uses the appropriate Signal type based on the context:
// Basic signal with initial value
let x = signal!(5);
// Signal that depends on other signals
let y = signal!([x] x + 10);
// Signal with side effect
let z = signal!(<old_val, new_val> [x, y] {
let sum = x + y;
sum * 2
}; println!("z changed from {} to {}", old_val, new_val));
You can specify custom effects that run when signals change:
let x = signal!(1);
let y = signal!(<old_y, new_y> [x] x * 3; {
println!("y changed from {} to {}", old_y, new_y);
// Perform side effects here
});
reactivity::Signal for single-threaded applications where all signals are accessed from the same threadreactivity::sync::Signal when signals need to be shared across multiple threadsThis project is dual-licensed under either of:
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you shall be dual licensed as above, without any additional terms or conditions.