fluttercommunity / redux.dart

Redux for Dart
https://pub.dev/packages/redux
MIT License
515 stars 61 forks source link

Q: why doesn't store have a stream of dispatched actions? #54

Closed kentcb closed 4 years ago

kentcb commented 4 years ago

Hi there,

I've just found myself wanting Store to expose Stream<dynamic> get actions and am wondering why it doesn't.

I'm trying to test push notification logic in my app as best I can without actually integrating with third party code. When push notifications are received (which happens in the widget layer), they are immediately dispatched in a "raw" state inside an action. The middleware then processes the raw data and dispatches either a failure action, or - depending on the data in the push notification - a more specific action with strongly-typed data. The failure actions just end up in the log - nothing more.

So I'm trying to write tests that send dodgy push notifications via a dispatch and then verifying that an appropriate failure action is dispatched. But without store.actions, this is a bit messy to achieve. I instead need my tests to have some level of control over the middleware set up for them, and this isn't great because until now my tests have been able to remain blissfully ignorant of that.

Anyway, just a question. Maybe there's a really good reason not to expose this, but I can't think of one.

kentcb commented 4 years ago

My workaround was to define my own middleware:

class CapturingMiddleware extends MiddlewareClass<AppState> {
  final actions = <dynamic>[];

  @override
  void call(Store<AppState> store, dynamic action, NextDispatcher next) {
    actions.add(action);
    next(action);
  }
}

This is obviously a super-dangerous memory leak, but it's only used in the context of tests, and a new one is created for each test.

I think this is actually a better/easier solution than hooking into a stream for tests, but I still do wonder whether a stream of actions makes sense.

brianegan commented 4 years ago

Heya @kentcb -- sorry, missed this one. The store doesn't provide this out of the box, but I do have the Epics middleware which is meant to help out with just this kinda thing: https://github.com/brianegan/dart_redux_epics

Does that help?

MichaelMarner commented 4 years ago

I feel as though keeping this for Epics or other middleware is the better approach here. In general, consumers of the store should only care about the current state of the store - how the store got into a particular state (ie what actions were dispatched) should not be relevant.

An Epic is the perfect use for logging errors.

kentcb commented 4 years ago

Hmm, this wasn't about logging so much as capturing an in-memory record of actions so that tests can verify behavior. I'm happy with my current approach (CapturingMiddleware) and can appreciate why an epic helps alleviate the need for an action stream.

Unfortunately, my ability to use epics in the one situation I've really needed them (managing timers) has been completely thwarted by this issue, but that's another story.