Wraps a callback function into a reusable, batched, and untracked action.
An action is a higher-order function that takes a callback and returns a new function with the exact same signature. When the returned function is executed, it runs the original callback inside both a batch and an untracked block.
Why use action instead of batch?#
-
Reusability:
batch(fn)executes the callback immediately. In contrast,action(fn)returns a reusable function that you can store, pass around, and invoke multiple times to perform batch transactions on demand. -
Untracked Execution: The callback runs inside
untracked. If you invoke the action from within aneffector acomputedsignal, the outer reactive context will not establish subscriptions to any signals read inside the action.
Example: Comparing Normal Updates vs. Action Batching#
Without Actions (Standard Sequential Updates)
Every signal write immediately notifies active subscribers. This causes transient states and redundant, intermediate executions:
import 'package:preact_signals/preact_signals.dart';
final a = signal('a');
final b = signal('b');
void main() {
// Set up a subscriber effect
effect(() => print('${a.value} ${b.value}'));
// Prints immediately: "a b"
a.value = 'aa'; // Prints: "aa b"
b.value = 'bb'; // Prints: "aa bb"
}
Total prints: 3 (initial execution + 2 updates).
With Actions (Coalesced Transaction)
By wrapping the state-mutating function in action, all updates are postponed and flushed in a single notification block once the function completes:
import 'package:preact_signals/preact_signals.dart';
final a = signal('a');
final b = signal('b');
// Create a reusable action
final updateFields = action((String nextA, String nextB) {
a.value = nextA;
b.value = nextB;
});
void main() {
effect(() => print('${a.value} ${b.value}'));
// Prints immediately: "a b"
updateFields('aa', 'bb');
// The effect is deferred during execution and triggers exactly once at the end.
// Prints: "aa bb"
}
Total prints: 2 (initial execution + 1 coalesced update).
Type-Safety & Extensions#
While action accepts any generic Function, Dart's static analysis benefits greatly from
type-safe variants or extensions.
-
Type-safe functions: Use
action0throughaction10(e.g.action2(...)for 2 arguments) to preserve type arguments. -
Extensions: Call
.actiondirectly on any Dart function (e.g.,myFunction.action).
Type-Safe Variants & Extensions#
To ensure complete type safety and optimize static analysis in Dart, the package exposes distinct variants and extension methods corresponding to the number of arguments (from 0 up to 10):
| Variant / Extension | Description |
|---|---|
action0 |
Wraps a 0-argument callback function in a type-safe action. signature |
action1 |
Wraps a 1-argument callback function in a type-safe action. signature |
action2 |
Wraps a 2-argument callback function in a type-safe action. signature |
action3 |
Wraps a 3-argument callback function in a type-safe action. signature |
action4 |
Wraps a 4-argument callback function in a type-safe action. signature |
action5 |
Wraps a 5-argument callback function in a type-safe action. signature |
action6 |
Wraps a 6-argument callback function in a type-safe action. signature |
action7 |
Wraps a 7-argument callback function in a type-safe action. signature |
action8 |
Wraps an 8-argument callback function in a type-safe action. signature |
action9 |
Wraps a 9-argument callback function in a type-safe action. signature |
action10 |
Wraps a 10-argument callback function in a type-safe action. signature |
ActionExt0 |
Extension on a 0-argument function to wrap it in a type-safe action. signature |
ActionExt1 |
Extension on a 1-argument function to wrap it in a type-safe action. signature |
ActionExt2 |
Extension on a 2-argument function to wrap it in a type-safe action. signature |
ActionExt3 |
Extension on a 3-argument function to wrap it in a type-safe action. signature |
ActionExt4 |
Extension on a 4-argument function to wrap it in a type-safe action. signature |
ActionExt5 |
Extension on a 5-argument function to wrap it in a type-safe action. signature |
ActionExt6 |
Extension on a 6-argument function to wrap it in a type-safe action. signature |
ActionExt7 |
Extension on a 7-argument function to wrap it in a type-safe action. signature |
ActionExt8 |
Extension on an 8-argument function to wrap it in a type-safe action. signature |
ActionExt9 |
Extension on a 9-argument function to wrap it in a type-safe action. signature |
ActionExt10 |
Extension on a 10-argument function to wrap it in a type-safe action. signature |
Show Full API Signatures & Examples
action0#
Wraps a 0-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
Example Usage#
final increment = action0(() {
count.value++;
clicks.value++;
});
action1#
Wraps a 1-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
Example Usage#
final setName = action1((String newName) {
name.value = newName;
updatedAt.value = DateTime.now();
});
action2#
Wraps a 2-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
Example Usage#
final updateProfile = action2((String newName, int newAge) {
name.value = newName;
age.value = newAge;
});
action3#
Wraps a 3-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
Example Usage#
final setCoordinates = action3((double lat, double lng, String label) {
latitude.value = lat;
longitude.value = lng;
locationName.value = label;
});
action4#
Wraps a 4-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
Example Usage#
final updateUserData = action4((String name, int age, double score, bool active) {
userName.value = name;
userAge.value = age;
userScore.value = score;
userActive.value = active;
});
action5#
Wraps a 5-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
Example Usage#
final setConfig = action5((int w, int h, String title, bool dark, double opacity) {
width.value = w;
height.value = h;
appTitle.value = title;
themeDark.value = dark;
bgOpacity.value = opacity;
});
action6#
Wraps a 6-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
action7#
Wraps a 7-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
action8#
Wraps an 8-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
action9#
Wraps a 9-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
action10#
Wraps a 10-argument callback function in a type-safe action.
Executes fn inside a transaction-safe batch and untracked block.
ActionExt0#
Extension on a 0-argument function to wrap it in a type-safe action.
Enables calling .action directly on any 0-argument function to wrap it.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final count = signal(0);
final clicks = signal(0);
void incrementCount() {
count.value++;
clicks.value++;
}
// Create a batched, untracked action from the function
final increment = incrementCount.action;
void main() {
effect(() => print('Count: ${count.value}, Clicks: ${clicks.value}'));
// Prints: "Count: 0, Clicks: 0"
increment();
// Updates both count and clicks inside a batch.
// Triggers the effect exactly once.
// Prints: "Count: 1, Clicks: 1"
}
Methods#
ActionExt1#
Extension on a 1-argument function to wrap it in a type-safe action.
Enables calling .action directly on any 1-argument function to wrap it.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final name = signal('Jane');
final clicks = signal(0);
void updateName(String newName) {
name.value = newName;
clicks.value++;
}
// Create a batched, untracked action from the function
final setName = updateName.action;
void main() {
effect(() => print('Name: ${name.value}, Clicks: ${clicks.value}'));
// Prints: "Name: Jane, Clicks: 0"
setName('John');
// Updates both name and clicks inside a batch.
// Triggers the effect exactly once.
// Prints: "Name: John, Clicks: 1"
}
Methods#
ActionExt2#
Extension on a 2-argument function to wrap it in a type-safe action.
Enables calling .action directly on any 2-argument function to wrap it.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final name = signal('Jane');
final age = signal(25);
void updateProfile(String newName, int newAge) {
name.value = newName;
age.value = newAge;
}
// Create a batched, untracked action from the function
final setProfile = updateProfile.action;
void main() {
effect(() => print('Name: ${name.value}, Age: ${age.value}'));
// Prints: "Name: Jane, Age: 25"
setProfile('John', 30);
// Updates both name and age inside a batch.
// Triggers the effect exactly once.
// Prints: "Name: John, Age: 30"
}
Methods#
ActionExt3#
Extension on a 3-argument function to wrap it in a type-safe action.
Enables calling .action directly on any 3-argument function to wrap it.
Example Usage#
import 'package:preact_signals/preact_signals.dart';
final latitude = signal(0.0);
final longitude = signal(0.0);
final locationName = signal('Unknown');
void setCoordinates(double lat, double lng, String label) {
latitude.value = lat;
longitude.value = lng;
locationName.value = label;
}
// Create a batched, untracked action from the function
final setCoords = setCoordinates.action;
void main() {
effect(() => print('${locationName.value}: (${latitude.value}, ${longitude.value})'));
// Prints: "Unknown: (0.0, 0.0)"
setCoords(37.7749, -122.4194, 'San Francisco');
// Updates latitude, longitude, and locationName inside a batch.
// Triggers the effect exactly once.
// Prints: "San Francisco: (37.7749, -122.4194)"
}
Methods#
ActionExt4#
Extension on a 4-argument function to wrap it in a type-safe action.
Methods#
ActionExt5#
Extension on a 5-argument function to wrap it in a type-safe action.
Methods#
ActionExt6#
Extension on a 6-argument function to wrap it in a type-safe action.
Methods#
View Methods
R Function(A, B, C, D, E, F) action
Wraps the 6-argument function in a type-safe action.
ActionExt7#
Extension on a 7-argument function to wrap it in a type-safe action.
Methods#
View Methods
R Function(A, B, C, D, E, F, G) action
Wraps the 7-argument function in a type-safe action.
ActionExt8#
Extension on an 8-argument function to wrap it in a type-safe action.
Methods#
View Methods
R Function(A, B, C, D, E, F, G, H) action
Wraps the 8-argument function in a type-safe action.
ActionExt9#
Extension on a 9-argument function to wrap it in a type-safe action.
Methods#
View Methods
R Function(A, B, C, D, E, F, G, H, I) action
Wraps the 9-argument function in a type-safe action.
ActionExt10#
Extension on a 10-argument function to wrap it in a type-safe action.
Methods#
View Methods
R Function(A, B, C, D, E, F, G, H, I, J) action
Wraps the 10-argument function in a type-safe action.