-
Notifications
You must be signed in to change notification settings - Fork 80
Description
Currently, for async actions that require a manual trigger (for example, createPost), the approach shown in the examples is to use an asyncSignal initialized with .data(null) to represent the “idle” state.
signals.dart/examples/crud_dio/lib/signals/post_signals.dart
Lines 7 to 9 in 157794c
| final post = asyncSignal<Post?>(AsyncState.data(null)); | |
| final postAddOrEdit = asyncSignal<Post?>(AsyncState.data(null)); | |
| final delete = asyncSignal<void>(AsyncState.data(null)); |
final createPost = asyncSignal<Post?>(AsyncState.data(null));When used this way, the state is typically handled like this:
switch (createPost.value) {
AsyncData<Post?> data => switch (data.value) {
null => 'idle',
Post() => 'success',
},
AsyncError() => 'error',
AsyncLoading() => 'loading',
}While this works, the intent of the code is not very clear. Using null to represent the idle state is implicit and makes the state model harder to reason about and communicate.
Proposed Solution
In riverpod, there is a dedicated MutationState abstraction designed specifically for this use case.
The idea is to introduce a mutationSignal that models mutation lifecycles explicitly.
final createPost = mutationSignal<Post>(); // Idle by defaultThis would allow consumers to handle states in a much clearer and more expressive way:
switch (createPost.value) {
MutationIdle() => 'idle',
MutationSuccess() => 'success',
MutationError() => 'error',
MutationPending() => 'pending',
}This approach removes the need for sentinel values like null, improves readability, and makes mutation intent explicit and self-documenting.