TypedMiddleware<State, Action> class

A convenience type for binding a piece of Middleware to an Action of a specific type. Allows for Type Safe Middleware and reduces boilerplate.

Example

In order to see what this utility function does, let's take a look at a regular example of running Middleware based on the Type of an action.

class AppState {
  final List<Item> items;

  AppState(this.items);
}
class LoadItemsAction {}
class UpdateItemsAction {}
class AddItemAction{}
class RemoveItemAction {}
class ShuffleItemsAction {}
class ReverseItemsAction {}
class ItemsLoadedAction<Item> {
  final List<Item> items;

  ItemsLoadedAction(this.items);
}

final loadItems = () { /* Function that loads a Future<List<Item>> */}
final saveItems = (List<Item> items) { /* Function that persists items */}

final middleware = (Store<AppState> store, action, NextDispatcher next) {
  if (action is LoadItemsAction) {
    loadItems()
      .then((items) => store.dispatch(new ItemsLoaded(items))
      .catchError((_) => store.dispatch(new ItemsNotLoaded());

    next(action);
  } else if (action is UpdateItemsAction ||
      action is AddItemAction ||
      action is RemoveItemAction ||
      action is ShuffleItemsAction ||
      action is ReverseItemsAction) {
    next(action);

    saveItems(store.state.items);
  } else {
    next(action);
  }
};

This works fine if you have one or two actions to handle, but you might notice it's getting a bit messy already. Let's see how this lib helps clean it up.

// First, let's start by breaking up our functionality into two middleware
// functions.
//
// The loadItemsMiddleware will only handle the `LoadItemsAction`s that
// are dispatched, so we can annotate the Type of action.
final loadItemsMiddleware = (
  Store<AppState> store,
  LoadItemsAction action,
  NextDispatcher next,
) {
  loadItems()
    .then((items) => store.dispatch(new ItemsLoaded(items))
    .catchError((_) => store.dispatch(new ItemsNotLoaded());

  next(action);
}

// The saveItemsMiddleware handles all actions that change the Items, but
// does not depend on the payload of the action. Therefore, `action` will
// remain dynamic.
final saveItemsMiddleware = (
  Store<AppState> store,
  dynamic action,
  NextDispatcher next,
) {
  next(action);

  saveItems(store.state.items);
}

// We will then wire up specific types of actions to a List of Middleware
// that handle those actions.
final List<Middleware<AppState>> middleware = [
  new TypedMiddleware<AppState, LoadTodosAction>(loadItemsMiddleware),
  new TypedMiddleware<AppState, AddTodoAction>(saveItemsMiddleware),
  new TypedMiddleware<AppState, ClearCompletedAction>(saveItemsMiddleware),
  new TypedMiddleware<AppState, ToggleAllAction>(saveItemsMiddleware),
  new TypedMiddleware<AppState, UpdateTodoAction>(saveItemsMiddleware),
  new TypedMiddleware<AppState, TodosLoadedAction>(saveItemsMiddleware),
];
Implemented types

Constructors

TypedMiddleware(void middleware(Store<State> store, Action action, NextDispatcher next))
Create a Middleware that is only executed when the dispatched action matches the Action type.

Properties

hashCode int
The hash code for this object.
no setterinherited
middleware → void Function(Store<State> store, Action action, NextDispatcher next)
A Middleware function that only works on actions of a specific type.
final
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

call(Store<State> store, dynamic action, NextDispatcher next) → dynamic
A Middleware function that intercepts a dispatched action
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited