Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add TypedMiddlewareBase abstraction #82

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
5.0.0
# 5.1.0

* Added option to create typed middelware class by extending `TypedMiddlewareBase<State, Action>`

# 5.0.0

* Preview version, same as 5.0.0-nullsafety

5.0.0-nullsafety
# 5.0.0-nullsafety

* Update to null safety
* Drop package:coverage
Expand Down
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,22 @@ loggingMiddleware(Store<int> store, action, NextDispatcher next) {
next(action);
}

// You can also create a middleware class bound to exact action type.
class CallMiddleware extends TypedMiddlewareBase<State, CallAction> {
@override
dynamic dispatch(
Store<String> store, CallAction action, NextDispatcher next) {
service.call(action.phone);
next(action);
}
}

main() {
// Create the store with our Reducer and Middleware
final store = new Store<int>(
counterReducer,
initialState: 0,
middleware: [loggingMiddleware],
middleware: [loggingMiddleware, CallMiddleware()],
);

// Render our State right away
Expand Down
56 changes: 48 additions & 8 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,50 @@ class TypedReducer<State, Action> implements ReducerClass<State> {
}
}

/// A convenience type to build a Middleware to an Action
/// of a specific type. Allows for Type Safe Middleware.
///
/// ### Example
/// ```
/// class CustomMiddleware extends TypedMiddlewareBase<AppState, CustomAction> {
/// @override
/// dynamic dispatch(
/// Store<AppState> store,
/// CustomAction action,
/// NextDispatcher next,
/// ) {
/// next(action);
/// }
/// }
/// ```
/// We will then wire up specific types of actions to a List of Middleware
/// that handle those actions.
/// ```
/// final List<Middleware<AppState>> middleware = [
/// CallMiddleware(),
/// LoginMiddleware(),
/// LogoutMiddleware(),
/// ];
/// ```
abstract class TypedMiddlewareBase<State, Action>
implements MiddlewareClass<State> {
/// A [Middleware] function that only works on actions of a specific type.
dynamic dispatch(
Store<State> store,
Action action,
NextDispatcher next,
);

@override
dynamic call(Store<State> store, dynamic action, NextDispatcher next) {
if (action is Action) {
return dispatch(store, action, next);
} else {
return next(action);
}
}
}

/// A convenience type for binding a piece of Middleware to an Action
/// of a specific type. Allows for Type Safe Middleware and reduces boilerplate.
///
Expand Down Expand Up @@ -211,7 +255,8 @@ class TypedReducer<State, Action> implements ReducerClass<State> {
/// new TypedMiddleware<AppState, TodosLoadedAction>(saveItemsMiddleware),
/// ];
/// ```
class TypedMiddleware<State, Action> implements MiddlewareClass<State> {
class TypedMiddleware<State, Action>
extends TypedMiddlewareBase<State, Action> {
/// A [Middleware] function that only works on actions of a specific type.
final dynamic Function(
Store<State> store,
Expand All @@ -224,13 +269,8 @@ class TypedMiddleware<State, Action> implements MiddlewareClass<State> {
TypedMiddleware(this.middleware);

@override
dynamic call(Store<State> store, dynamic action, NextDispatcher next) {
if (action is Action) {
return middleware(store, action, next);
} else {
return next(action);
}
}
dynamic dispatch(Store<State> store, Action action, NextDispatcher next) =>
middleware(store, action, next);
}

/// Defines a utility function that combines several reducers.
Expand Down
10 changes: 10 additions & 0 deletions test/test_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,18 @@ class ThunkMiddleware<State> implements MiddlewareClass<State> {
}
}

class TypedTestMiddleware extends TypedMiddlewareBase<String, TypedTestAction> {
@override
dynamic dispatch(
Store<String> store, TypedTestAction action, NextDispatcher next) {
next('TypedTestMiddleware called');
}
}

class TestAction1 {}

class TestAction2 {}

class TestAction3 {}

class TypedTestAction {}
5 changes: 5 additions & 0 deletions test/utils_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ void main() {
middleware: [
TypedMiddleware<String, TestAction1>(testAction1Middleware),
TypedMiddleware<String, TestAction2>(testAction2Middleware),
TypedTestMiddleware(),
],
);

Expand All @@ -116,6 +117,9 @@ void main() {

store.dispatch(TestAction2());
expect(store.state, 'testAction2Middleware called');

store.dispatch(TypedTestAction());
expect(store.state, 'TypedTestMiddleware called');
});

test(
Expand All @@ -127,6 +131,7 @@ void main() {
initialState: initialState,
middleware: [
TypedMiddleware<String, TestAction1>(testAction1Middleware),
TypedTestMiddleware(),
],
);

Expand Down