Effect class
The effect
function is the last piece that makes everything reactive. When you access a signal inside its callback function, that signal and every dependency of said signal will be activated and subscribed to. In that regard it is very similar to computed(fn)
. By default all updates are lazy, so nothing will update until you access a signal inside effect
.
import 'package:signals/signals.dart';
final name = signal("Jane");
final surname = signal("Doe");
final fullName = computed(() => name.value + " " + surname.value);
// Logs: "Jane Doe"
effect(() => print(fullName.value));
// Updating one of its dependencies will automatically trigger
// the effect above, and will print "John Doe" to the console.
name.value = "John";
You can destroy an effect and unsubscribe from all signals it was subscribed to, by calling the returned function.
import 'package:signals/signals.dart';
final name = signal("Jane");
final surname = signal("Doe");
final fullName = computed(() => name.value + " " + surname.value);
// Logs: "Jane Doe"
final dispose = effect(() => print(fullName.value));
// Destroy effect and subscriptions
dispose();
// Update does nothing, because no one is subscribed anymore.
// Even the computed `fullName` signal won't change, because it knows
// that no one listens to it.
surname.value = "Doe 2";
Cleanup Callback
You can also return a cleanup function from an effect. This function will be called when the effect is destroyed.
import 'package:signals/signals.dart';
final s = signal(0);
final dispose = effect(() {
print(s.value);
return () => print('Effect destroyed');
});
// Destroy effect and subscriptions
dispose();
On Dispose Callback
You can also pass a callback to effect
that will be called when the effect is destroyed.
import 'package:signals/signals.dart';
final s = signal(0);
final dispose = effect(() {
print(s.value);
}, onDispose: () => print('Effect destroyed'));
// Destroy effect and subscriptions
dispose();
Warning About Cycles
Mutating a signal inside an effect will cause an infinite loop, because the effect will be triggered again. To prevent this, you can use untracked(fn)
to read a signal without subscribing to it.
import 'dart:async';
import 'package:signals/signals.dart';
Future<void> main() async {
final completer = Completer<void>();
final age = signal(0);
effect(() {
print('You are ${age.value} years old');
age.value++; // <-- This will throw a cycle error
});
await completer.future;
}
- Implemented types
Constructors
- Effect(EffectCallback compute, {String? debugLabel})
-
The
effect
function is the last piece that makes everything reactive. When you access a signal inside its callback function, that signal and every dependency of said signal will be activated and subscribed to. In that regard it is very similar tocomputed(fn)
. By default all updates are lazy, so nothing will update until you access a signal insideeffect
.
Properties
- debugLabel → String?
-
Debug label for Debug Mode
final
- disposed ↔ bool
-
Check if the effect is disposed
getter/setter pair
- globalId → int
-
Global ID of the signal
final
- hashCode → int
-
The hash code for this object.
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
sources
→ Iterable<
ReadonlySignal> -
@internal for testing getter to track all the signals currently
subscribed in the effect
no setter
Methods
-
dispose(
) → void -
Dispose of the instance
override
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onDispose(
void cleanup()) → EffectCleanup - Add a cleanup function to be called when the signal is disposed
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited