Skip to content

Commit

Permalink
Merge pull request #52 from andrasferenczi/master
Browse files Browse the repository at this point in the history
Have dispatch return a value
  • Loading branch information
brianegan authored Nov 11, 2019
2 parents a2bbdac + 01f5ad5 commit 167cdce
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 10 deletions.
9 changes: 4 additions & 5 deletions lib/src/store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ abstract class ReducerClass<State> {
/// counterReducer,
/// middleware: [loggingMiddleware],
/// );
typedef void Middleware<State>(
typedef dynamic Middleware<State>(
Store<State> store,
dynamic action,
NextDispatcher next,
Expand Down Expand Up @@ -101,7 +101,7 @@ typedef void Middleware<State>(
/// );
abstract class MiddlewareClass<State> {
/// A [Middleware] function that intercepts a dispatched action
void call(Store<State> store, dynamic action, NextDispatcher next);
dynamic call(Store<State> store, dynamic action, NextDispatcher next);
}

/// The contract between one piece of middleware and the next in the chain. Use
Expand All @@ -111,7 +111,7 @@ abstract class MiddlewareClass<State> {
/// Middleware can optionally pass the original action or a modified action to
/// the next piece of middleware, or never call the next piece of middleware at
/// all.
typedef void NextDispatcher(dynamic action);
typedef dynamic NextDispatcher(dynamic action);

/// Creates a Redux store that holds the app state tree.
///
Expand Down Expand Up @@ -264,8 +264,7 @@ class Store<State> {
/// intercept actions, and can modify actions or stop them from passing
/// through to the reducer.
dynamic dispatch(dynamic action) {
_dispatchers[0](action);
return action;
return _dispatchers[0](action);
}

/// Closes down the Store so it will no longer be operational. Only use this
Expand Down
6 changes: 3 additions & 3 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,11 @@ class TypedMiddleware<State, Action> implements MiddlewareClass<State> {
TypedMiddleware(this.middleware);

@override
void call(Store<State> store, dynamic action, NextDispatcher next) {
dynamic call(Store<State> store, dynamic action, NextDispatcher next) {
if (action is Action) {
middleware(store, action, next);
return middleware(store, action, next);
} else {
next(action);
return next(action);
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions test/middleware_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'package:redux/redux.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -75,5 +76,28 @@ void main() {

expect(middleware1.counter, equals(2));
});

test('dispatch returns the value from middleware', () async {
final passthrough = PassThroughMiddleware<String>();
final thunk = ThunkMiddleware<String>();
Future<void> thunkAction(Store<String> store) async {
await Future<void>.delayed(Duration(milliseconds: 5));
store.dispatch("changed");
}

final store = Store<String>(
stringReducer,
initialState: 'hello',
middleware: [passthrough, thunk],
);

final awaitableAction = store.dispatch(thunkAction) as Future<void>;

// Did not change yet
expect(store.state, equals('hello'));
await awaitableAction;
// The effect has taken place
expect(store.state, equals('changed'));
});
});
}
21 changes: 19 additions & 2 deletions test/test_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ class StringReducer extends ReducerClass<String> {

class IncrementMiddleware extends MiddlewareClass<String> {
int counter = 0;
final _invocationsController =
StreamController<String>.broadcast(sync: true);
final _invocationsController = StreamController<String>.broadcast(sync: true);

Stream<String> get invocations => _invocationsController.stream;

Expand Down Expand Up @@ -72,6 +71,24 @@ class ExtraActionIfDispatchedIncrementMiddleware extends IncrementMiddleware {
}
}

class PassThroughMiddleware<State> implements MiddlewareClass<State> {
@override
dynamic call(Store<State> store, dynamic action, NextDispatcher next) {
return next(action);
}
}

class ThunkMiddleware<State> implements MiddlewareClass<State> {
@override
dynamic call(Store<State> store, dynamic action, NextDispatcher next) {
if (action is Function) {
return action(store);
} else {
return next(action);
}
}
}

class TestAction1 {}

class TestAction2 {}
Expand Down

0 comments on commit 167cdce

Please sign in to comment.