asyncredux-action-status
Checks an AsyncRedux (Flutter) action's completion status using ActionStatus right after the dispatch returns. Use only when you need to know whether an action completed, whether it failed with an error, what error it produced, or how to navigate based on success or failure.
Best use case
asyncredux-action-status is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Checks an AsyncRedux (Flutter) action's completion status using ActionStatus right after the dispatch returns. Use only when you need to know whether an action completed, whether it failed with an error, what error it produced, or how to navigate based on success or failure.
Teams using asyncredux-action-status should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/asyncredux-action-status/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How asyncredux-action-status Compares
| Feature / Agent | asyncredux-action-status | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Checks an AsyncRedux (Flutter) action's completion status using ActionStatus right after the dispatch returns. Use only when you need to know whether an action completed, whether it failed with an error, what error it produced, or how to navigate based on success or failure.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# ActionStatus in AsyncRedux
The `ActionStatus` object provides information about whether an action completed successfully or encountered errors. It is returned by `dispatchAndWait()` and related methods.
## Getting ActionStatus
Use `dispatchAndWait()` to get the status after an action completes:
```dart
var status = await dispatchAndWait(MyAction());
```
From within an action, you can also use:
```dart
var status = await dispatchAndWait(SomeOtherAction());
```
## ActionStatus Properties
### Completion Status
- **`isCompleted`**: Returns `true` if the action has finished executing (whether successful or failed)
- **`isCompletedOk`**: Returns `true` if the action finished without errors in both `before()` and `reduce()` methods
- **`isCompletedFailed`**: Returns `true` if the action encountered errors (opposite of `isCompletedOk`)
### Error Information
- **`originalError`**: The error originally thrown by `before()` or `reduce()`, before any modification
- **`wrappedError`**: The error after processing by the action's `wrapError()` method
### Execution Tracking
These properties track which lifecycle methods have completed:
- **`hasFinishedMethodBefore`**: Returns `true` if the `before()` method completed
- **`hasFinishedMethodReduce`**: Returns `true` if the `reduce()` method completed
- **`hasFinishedMethodAfter`**: Returns `true` if the `after()` method completed
Note: The execution tracking properties are primarily meant for testing and debugging. In production code, focus on `isCompletedOk` and `isCompletedFailed`.
## Common Use Cases
### Conditional Navigation After Success
The most common production use is checking if an action succeeded before navigating:
```dart
// In a widget callback
Future<void> _onSavePressed() async {
var status = await context.dispatchAndWait(SaveFormAction());
if (status.isCompletedOk) {
Navigator.pop(context);
}
}
```
Another example with push navigation:
```dart
Future<void> _onLoginPressed() async {
var status = await context.dispatchAndWait(LoginAction(
email: emailController.text,
password: passwordController.text,
));
if (status.isCompletedOk) {
Navigator.pushReplacementNamed(context, '/home');
}
// If failed, the error will be shown via UserExceptionDialog
}
```
### Testing Action Errors
Use ActionStatus to verify that actions throw expected errors:
```dart
test('MyAction fails with invalid input', () async {
var store = Store<AppState>(initialState: AppState.initial());
var status = await store.dispatchAndWait(MyAction(value: -1));
expect(status.isCompletedFailed, isTrue);
expect(status.wrappedError, isA<UserException>());
expect((status.wrappedError as UserException).msg, "Value must be positive");
});
```
### Testing Action Success
```dart
test('SaveAction completes successfully', () async {
var store = Store<AppState>(initialState: AppState.initial());
var status = await store.dispatchAndWait(SaveAction(data: validData));
expect(status.isCompletedOk, isTrue);
expect(store.state.saved, isTrue);
});
```
### Checking Original vs Wrapped Error
When your action uses `wrapError()` to transform errors, you can inspect both:
```dart
class MyAction extends AppAction {
@override
Future<AppState?> reduce() async {
throw Exception('Network error');
}
@override
Object? wrapError(Object error, StackTrace stackTrace) {
return UserException('Could not save. Please try again.');
}
}
// In test:
var status = await store.dispatchAndWait(MyAction());
expect(status.originalError, isA<Exception>()); // The original Exception
expect(status.wrappedError, isA<UserException>()); // The wrapped UserException
```
## Action Lifecycle and Status
The action lifecycle runs in this order:
1. `before()` - Runs first, can be used for preconditions
2. `reduce()` - Runs second (only if `before()` succeeded)
3. `after()` - Runs last, always executes (like a finally block)
The `isCompletedOk` property is `true` only if both `before()` and `reduce()` completed without errors. Note that errors in `after()` do not affect `isCompletedOk`.
If `before()` throws an error, `reduce()` will not run, but `after()` will still execute.
## Best Practices
1. **Use state changes for UI updates**: In production, prefer checking state changes rather than action status. Reserve ActionStatus for cases where you need to perform side effects (like navigation) based on success/failure.
2. **Use `isCompletedOk` for navigation**: The common pattern is to navigate only after an action succeeds:
```dart
if (status.isCompletedOk) Navigator.pop(context);
```
3. **Use `wrappedError` in tests**: When testing error handling, check `wrappedError` to see what the user will actually see (after `wrapError()` processing).
4. **Use `originalError` for debugging**: When you need to see the underlying error before any transformation, use `originalError`.
## References
URLs from the documentation:
- https://asyncredux.com/flutter/advanced-actions/action-status
- https://asyncredux.com/flutter/basics/dispatching-actions
- https://asyncredux.com/flutter/basics/failed-actions
- https://asyncredux.com/flutter/advanced-actions/errors-thrown-by-actions
- https://asyncredux.com/flutter/advanced-actions/before-and-after-the-reducer
- https://asyncredux.com/flutter/advanced-actions/redux-action
- https://asyncredux.com/flutter/miscellaneous/navigation
- https://asyncredux.com/flutter/testing/store-tester
- https://asyncredux.com/flutter/testing/dispatch-wait-and-expect
- https://asyncredux.com/flutter/testing/testing-user-exceptionsRelated Skills
acc-create-action
Generates ADR Action classes for PHP 8.5. Creates single-responsibility HTTP endpoint handlers with PSR-7 support. Includes unit tests.
acc-check-leaky-abstractions
Detects leaky abstractions in PHP code. Identifies implementation details exposed in interfaces, concrete returns from abstract methods, framework leakage into domain, and infrastructure concerns in application layer.
abaqus-interaction
Define contact and interactions - contact pairs, tie constraints, connectors. Use when user mentions contact, friction, tie, parts touching, or bonded surfaces.
process-needs-action
This skill should be used when you need to process pending action items from a designated folder and generate detailed implementation plans based on organizational rules. Ideal for task management workflows that require systematic processing of pending items, plan creation, and dashboard updates. Use when the user asks to process action items, review pending tasks, or generate plans from a backlog.
pattern-extraction
Extract design systems, architecture patterns, and methodology from codebases into reusable skills and documentation. Use when analyzing a project to capture patterns, creating skills from existing code, extracting design tokens, or documenting how a project was built. Triggers on "extract patterns", "extract from this repo", "analyze this codebase", "create skills from this project", "extract design system".
asyncredux-wait-fail-succeed
Show loading states and handle action failures in widgets. Covers `isWaiting(ActionType)` for spinners, `isFailed(ActionType)` for error states, `exceptionFor(ActionType)` for error messages, and `clearExceptionFor()` to reset failure states.
asyncredux-wait-condition
Use `waitCondition()` inside actions to pause execution until state meets criteria. Covers waiting for price thresholds, coordinating between actions, and implementing conditional workflows.
asyncredux-user-exceptions
Handle user-facing errors with UserException. Covers throwing UserException from actions, setting up UserExceptionDialog, customizing error dialogs with `onShowUserExceptionDialog`, and using UserExceptionAction for non-interrupting error display.
asyncredux-sync-actions
Creates AsyncRedux (Flutter) synchronous actions that update state immediately by implementing reduce() to return a new state.
asyncredux-streams-timers
Manage Streams and Timers with AsyncRedux. Covers creating actions to start/stop streams, storing stream subscriptions in store props, dispatching actions from stream callbacks, and proper cleanup with disposeProps().
asyncredux-state-access
Access store state in widgets using `context.state`, `context.select()`, and `context.read()`. Covers when to use each method, setting up BuildContext extensions, and optimizing widget rebuilds with selective state access.
asyncredux-setup
Initialize, setup and configure AsyncRedux in a Flutter app. Use it whenever starting a new AsyncRedux project, or when the user requests.