Skip to content

Signal

Signals are the cornerstone of reactivity in solidart. They contain values that change over time; when you change a signal’s value, it automatically updates anything that uses it.

Let’s see how to create a Signal:

Import the flutter_solidart package:

import 'package:flutter_solidart/flutter_solidart.dart';

Next create the signal with:

final counter = Signal(0);

The argument passed to the create call is the initial value, and the return value is the signal.

To retrieve the current value, you can use:

print(counter.value); // prints 0

To change the value, you can use:

// Set the value to 2
counter.value = 2;
// Update the value based on the current value
counter.updateValue((value) => value * 2);

Make a read-only signal

If you want to create a signal that can only be read but not modified directly, you can use the toReadSignal method.

final counter = Signal(0);
final readOnlyCounter = counter.toReadSignal();
print(readOnlyCounter.value); // prints 0
// The code below is invalid and will cause a compile-time error because no setter is present
readOnlyCounter.value = 2;

Observe the signal

To react to changes in a Signal you can use the observe method:

final counter = Signal(0);
counter.observe((previousValue, value) {
print("Counter changed from $previousValue to $value");
});

By default the observer is called for the next value change, but you can also call it immediately with the current value by passing fireImmediately: true:

counter.observe((previousValue, value) {
print("Counter changed from $previousValue to $value");
}, fireImmediately: true);

Or use an Effect if you need to react to multiple signals:

final counter = Signal(0);
final doubleCounter = Signal(0);
Effect(() {
print('Counter is ${counter.value}, double is ${doubleCounter.value}');
});

The effect will run immediately.

Access the previous value

A Signal contains the previous value in addition to the current value. You can access it using the previousValue property:

final counter = Signal(0);
print(counter.hasPreviousValue); // prints false (no previous value is present)
print(counter.previousValue); // prints null (no previous value is present)
counter.value = 1;
print(counter.hasPreviousValue); // prints true (previous value is present)
print(counter.previousValue); // prints 0

As you can see the previousValue is null until the first time the value is changed. You can check if a previous value is present using the hasPreviousValue property.

By default the previous value is tracked. If you want to disable it, you can pass trackPreviousValue: false to the Signal constructor:

final counter = Signal(0, trackPreviousValue: false);

or globally using the SolidartConfig:

SolidartConfig.trackPreviousValue = false;
// do it before runApp()

Await until a condition is met

You can use the until method to wait for a signal to meet a specific condition:

final counter = Signal(0);
await counter.until((value) => value >= 5, timeout: Duration(seconds: 10));

By default no timeout is set, so the until method will wait indefinitely until the condition is met. This is useful when you want to wait for a signal to reach a certain value before proceeding with your code.