leptos_use

Function sync_signal

Source
pub fn sync_signal<T>(
    left: impl Into<UseRwSignal<T>>,
    right: impl Into<UseRwSignal<T>>,
) -> impl Fn() + Clone
where T: Clone + 'static,
Expand description

Two-way Signals synchronization.

Note: Please consider first if you can achieve your goals with the “Good Options” described in the Leptos book Only if you really have to, use this function. This is, in effect, the “If you really must…” option.

§Demo

Link to Demo

§Usage

let (a, set_a) = create_signal(1);
let (b, set_b) = create_signal(2);

let stop = sync_signal((a, set_a), (b, set_b));

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 1, b: 1

set_b.set(3);

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 3, b: 3

set_a.set(4);

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 4, b: 4

§RwSignal

You can mix and match RwSignals and Signal-WriteSignal pairs.

let (a, set_a) = create_signal(1);
let (b, set_b) = create_signal(2);
let c_rw = create_rw_signal(3);
let d_rw = create_rw_signal(4);

sync_signal((a, set_a), c_rw);
sync_signal(d_rw, (b, set_b));
sync_signal(c_rw, d_rw);

§One directional

You can synchronize a signal only from left to right or right to left.

let (a, set_a) = create_signal(1);
let (b, set_b) = create_signal(2);

let stop = sync_signal_with_options(
    (a, set_a),
    (b, set_b),
    SyncSignalOptions::default().direction(SyncDirection::LeftToRight)
);

set_b.set(3); // doesn't sync

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 1, b: 3

set_a.set(4);

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 4, b: 4

§Custom Transform

You can optionally provide custom transforms between the two signals.

let (a, set_a) = create_signal(10);
let (b, set_b) = create_signal(2);

let stop = sync_signal_with_options(
    (a, set_a),
    (b, set_b),
    SyncSignalOptions::with_transforms(
        |left| *left * 2,
        |right| *right / 2,
    ),
);

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 10, b: 20

set_b.set(30);

logging::log!("a: {}, b: {}", a.get(), b.get()); // a: 15, b: 30
§Different Types

SyncSignalOptions::default() is only defined if the two signal types are identical. Otherwise, you have to initialize the options with with_transforms or with_assigns instead of default.

let (a, set_a) = create_signal("10".to_string());
let (b, set_b) = create_signal(2);

let stop = sync_signal_with_options(
    (a, set_a),
    (b, set_b),
    SyncSignalOptions::with_transforms(
        |left: &String| i32::from_str(left).unwrap_or_default(),
        |right: &i32| right.to_string(),
    ),
);
#[derive(Clone)]
pub struct Foo {
    bar: i32,
}

let (a, set_a) = create_signal(Foo { bar: 10 });
let (b, set_b) = create_signal(2);

let stop = sync_signal_with_options(
    (a, set_a),
    (b, set_b),
    SyncSignalOptions::with_assigns(
        |b: &mut i32, a: &Foo| *b = a.bar,
        |a: &mut Foo, b: &i32| a.bar = *b,
    ),
);