askill
asyncredux-abort-dispatch

asyncredux-abort-dispatchSafety 90Repository

Stops an AsyncRedux (Flutter) action from dispatching. Use only when the user mentions abortDispatch(), or explicitly asks to abort or prevent dispatch under certain conditions.

0 stars
1.2k downloads
Updated 2/5/2026

Package Files

Loading files...
SKILL.md

AsyncRedux Aborting the Dispatch

What is abortDispatch()?

The abortDispatch() method is an optional method on ReduxAction that lets you conditionally prevent an action from executing. When this method returns true, the entire action is skipped—before(), reduce(), and after() will NOT run, and state remains unchanged.

class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() {
    // Return true to abort, false to proceed
    return someCondition;
  }

  @override
  AppState? reduce() {
    // Only runs if abortDispatch() returned false
    return state.copy(/* ... */);
  }
}

Basic Usage

The simplest use case is checking a condition before allowing the action to proceed:

class LoadUserProfile extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;

  @override
  Future<AppState?> reduce() async {
    // Only runs if user is logged in
    final profile = await api.fetchProfile(state.user!.id);
    return state.copy(profile: profile);
  }
}

Action Lifecycle with abortDispatch()

When abortDispatch() returns true, the complete action lifecycle is skipped:

class MyAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.shouldSkip;  // If true:

  @override
  void before() {
    // NOT called when aborted
  }

  @override
  AppState? reduce() {
    // NOT called when aborted
  }

  @override
  void after() {
    // NOT called when aborted
  }
}

This differs from throwing an error in before(), which would still cause after() to run.

Authentication Guard Pattern

A common pattern is creating a base action that requires authentication:

/// Base action that requires an authenticated user
abstract class AuthenticatedAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user == null;
}

/// Actions extending this will only run when user is logged in
class FetchUserOrders extends AuthenticatedAction {
  @override
  Future<AppState?> reduce() async {
    // Safe to use state.user! here - abortDispatch ensures it's not null
    final orders = await api.getOrders(state.user!.id);
    return state.copy(orders: orders);
  }
}

class UpdateUserSettings extends AuthenticatedAction {
  final Settings newSettings;
  UpdateUserSettings(this.newSettings);

  @override
  Future<AppState?> reduce() async {
    await api.updateSettings(state.user!.id, newSettings);
    return state.copy(settings: newSettings);
  }
}

Creating Base Actions with Abort Logic

You can combine multiple abort conditions in a base action:

abstract class AppAction extends ReduxAction<AppState> {
  // Override in subclasses to add action-specific abort logic
  bool shouldAbort() => false;

  @override
  bool abortDispatch() {
    // Global abort conditions
    if (state.isMaintenanceMode) return true;
    if (state.isAppLocked) return true;

    // Action-specific abort conditions
    return shouldAbort();
  }
}

class RefreshData extends AppAction {
  @override
  bool shouldAbort() {
    // Don't refresh if data is still fresh
    return state.lastRefresh != null &&
        DateTime.now().difference(state.lastRefresh!) < Duration(minutes: 5);
  }

  @override
  Future<AppState?> reduce() async {
    final data = await api.fetchData();
    return state.copy(data: data, lastRefresh: DateTime.now());
  }
}

Role-Based Authorization

Use abortDispatch() to implement role-based access control:

abstract class AdminAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.user?.role != UserRole.admin;
}

class DeleteAllUsers extends AdminAction {
  @override
  Future<AppState?> reduce() async {
    // Only admins can reach this code
    await api.deleteAllUsers();
    return state.copy(users: []);
  }
}

Conditional Feature Actions

Prevent actions when features are disabled:

class UsePremiumFeature extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => !state.user!.isPremium;

  @override
  AppState? reduce() {
    // Premium-only functionality
    return state.copy(/* ... */);
  }
}

Built-in Mixin: AbortWhenNoInternet

AsyncRedux provides AbortWhenNoInternet, a mixin that silently aborts actions when there's no internet connection:

class FetchLatestNews extends AppAction with AbortWhenNoInternet {
  @override
  Future<AppState?> reduce() async {
    // Only runs if internet is available
    final news = await api.fetchNews();
    return state.copy(news: news);
  }
}

Key characteristics of AbortWhenNoInternet:

  • No error dialogs are shown
  • No exceptions are thrown
  • The action is silently cancelled
  • Only checks if device internet is on/off (not server availability)

Compare with CheckInternet which shows an error dialog instead of silently aborting.

abortDispatch() vs Throwing in before()

Choose the right approach for your use case:

Approachafter() runs?Shows error?Use when
abortDispatch() returns trueNoNoSilently skip action
Throw in before()YesYes (if UserException)Show error to user
// Silent abort - user doesn't know action was skipped
class SilentRefresh extends ReduxAction<AppState> {
  @override
  bool abortDispatch() => state.isOffline;
  // ...
}

// Visible error - user sees message
class ExplicitRefresh extends ReduxAction<AppState> {
  @override
  void before() {
    if (state.isOffline) {
      throw UserException('Cannot refresh while offline');
    }
  }
  // ...
}

When to Use abortDispatch()

Good use cases:

  • Authentication guards (action requires logged-in user)
  • Authorization checks (action requires specific role/permission)
  • Feature flags (action only for premium users)
  • Freshness checks (don't refetch if data is recent)
  • Maintenance mode (disable certain actions globally)
  • Idempotency (skip if action's effect already applied)

Consider alternatives when:

  • You want the user to see an error message (throw UserException in before())
  • You need cleanup code to run (use before() + after() pattern)
  • You're implementing rate limiting (use Throttle or Debounce mixins)
  • You're preventing duplicate dispatches (use NonReentrant mixin)

Complete Example

// Base action with common abort logic
abstract class AppAction extends ReduxAction<AppState> {
  @override
  bool abortDispatch() {
    // Global maintenance mode check
    if (state.maintenanceMode) return true;
    return false;
  }
}

// Authenticated action that also checks maintenance mode
abstract class AuthenticatedAction extends AppAction {
  @override
  bool abortDispatch() {
    // Check parent conditions first
    if (super.abortDispatch()) return true;
    // Then check authentication
    return state.currentUser == null;
  }
}

// Admin action with full authorization chain
abstract class AdminAction extends AuthenticatedAction {
  @override
  bool abortDispatch() {
    if (super.abortDispatch()) return true;
    return state.currentUser?.role != UserRole.admin;
  }
}

// Concrete action using the hierarchy
class BanUser extends AdminAction {
  final String userId;
  BanUser(this.userId);

  @override
  Future<AppState?> reduce() async {
    // Only reaches here if:
    // 1. Not in maintenance mode
    // 2. User is logged in
    // 3. User is an admin
    await api.banUser(userId);
    return state.copy(
      users: state.users.where((u) => u.id != userId).toList(),
    );
  }
}

Important Notes

  • abortDispatch() is checked before before(), reduce(), and after()
  • When aborted, no state changes occur
  • The action is silently skipped—no errors are thrown or logged by default
  • Use this feature judiciously; the documentation warns it's "a powerful feature" that should only be used "if you are sure it is the right solution"

References

URLs from the documentation:

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

95/100Analyzed 2/9/2026

A comprehensive and high-quality technical reference for the AsyncRedux 'abortDispatch' feature in Flutter. It includes clear patterns for authentication, authorization, and feature flags, along with a detailed comparison to alternative error-handling strategies.

90
100
80
95
95

Metadata

Licenseunknown
Version-
Updated2/5/2026
Publishermajiayu000

Tags

api