Signal

Struct Signal 

Source
pub struct Signal<T> { /* private fields */ }
Expand description

A reactive signal that holds a value, tracks dependencies, and triggers effects.

Signal<T> behaves similarly to a traditional “Property” (getter/setter), but on top of that, it automatically tracks which reactive computations or effects access it. When its value changes, all dependent effects are automatically re-run.

In short:

  • Like a Property: provides get() and set() for accessing and updating the value.
  • Adds tracking: automatically records dependencies when read inside reactive contexts, and automatically triggers dependent Effects when updated.

§Type Parameters

  • T: The type of the value stored in the signal. Must implement Eq.

§Memory Management Note

When referencing Signal instances that belong to other struct instances (for example, when one ViewModel holds references to signals in another ViewModel), you must store them as Weak<Signal<T>> obtained via Rc::downgrade instead of cloning a strong Rc. Failing to do so can create reference cycles between the structs and their dependent effects, preventing proper cleanup and causing memory leaks.

§Examples

§Basic usage

use std::rc::Rc;
use reactive_cache::Signal;

let signal = Signal::new(10);
assert_eq!(*signal.get(), 10);

signal.set(20);
assert_eq!(*signal.get(), 20);

§Using inside a struct

use std::rc::Rc;
use reactive_cache::Signal;

struct ViewModel {
    counter: Rc<Signal<i32>>,
    name: Rc<Signal<String>>,
}

let vm = ViewModel {
    counter: Signal::new(0).into(),
    name: Signal::new("Alice".to_string()).into(),
};

assert_eq!(*vm.counter.get(), 0);
assert_eq!(*vm.name.get(), "Alice");

vm.counter.set(1);
vm.name.set("Bob".into());

assert_eq!(*vm.counter.get(), 1);
assert_eq!(*vm.name.get(), "Bob");

Implementations§

Source§

impl<T> Signal<T>

Source

pub fn new(value: T) -> Rc<Self>

Creates a new Signal with the given initial value.

§Examples

Basic usage:

use std::rc::Rc;
use reactive_cache::Signal;

let signal = Signal::new(10);
assert_eq!(*signal.get(), 10);

Using inside a struct:

use std::rc::Rc;
use reactive_cache::Signal;

struct ViewModel {
    counter: Rc<Signal<i32>>,
    name: Rc<Signal<String>>,
}

let vm = ViewModel {
    counter: Signal::new(0),
    name: Signal::new("Alice".to_string()),
};

assert_eq!(*vm.counter.get(), 0);
assert_eq!(*vm.name.get(), "Alice");

// Update values
assert!(vm.counter.set(1));
assert!(vm.name.set("Bob".into()));

assert_eq!(*vm.counter.get(), 1);
assert_eq!(*vm.name.get(), "Bob");
Source

pub fn get(&self) -> Ref<'_, T>

Gets a reference to the current value, tracking dependencies and effects if inside a reactive context.

§Examples
use reactive_cache::Signal;

let signal = Signal::new(42);
assert_eq!(*signal.get(), 42);
Source

pub fn set(&self, value: T) -> bool
where T: Eq,

Sets the value of the signal.

Returns true if the value changed, all dependent memos are invalidated and dependent effects were triggered.

§Examples
use reactive_cache::Signal;

let signal = Signal::new(5);
assert_eq!(signal.set(10), true);
assert_eq!(*signal.get(), 10);

// Setting to the same value returns false
assert_eq!(signal.set(10), false);

Trait Implementations§

Source§

impl<T: Default> Default for Signal<T>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for Signal<T>

§

impl<T> !RefUnwindSafe for Signal<T>

§

impl<T> !Send for Signal<T>

§

impl<T> !Sync for Signal<T>

§

impl<T> Unpin for Signal<T>
where T: Unpin,

§

impl<T> !UnwindSafe for Signal<T>

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.