Skip to content

Commit 5859efe

Browse files
authored
v2.1.1 (#6)
* add dispatchMany and extensions * docs * cancel subscription
1 parent 9048d31 commit 5859efe

File tree

4 files changed

+95
-6
lines changed

4 files changed

+95
-6
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.1.1 - Oct 30, 2020
2+
3+
- Add `RxReduxStore.dispatchMany(Stream<A>)`: Dispatch a `Stream` of actions to store.
4+
- Add extension method `dispatchTo` on `A` and `Stream<A>`, eg: `anAction.dispatchTo(store)`, `streamOfActions.dispatchTo(store)`.
5+
16
## 2.1.0 - Aug 28, 2020
27

38
- State stream returned from `RxReduxStore` will not replay the latest state

lib/src/store.dart

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SideEffect<A, S> _onEachActionSideEffect<A, S>(StreamSink<A> outputSink) {
2929
/// Redux store based on [Stream].
3030
class RxReduxStore<A, S> {
3131
final void Function(A) _dispatch;
32+
final void Function(Stream<A>) _dispatchMany;
3233

3334
final GetState<S> _getState;
3435
final Stream<S> _stateStream;
@@ -38,6 +39,7 @@ class RxReduxStore<A, S> {
3839

3940
const RxReduxStore._(
4041
this._dispatch,
42+
this._dispatchMany,
4143
this._getState,
4244
this._stateStream,
4345
this._actionStream,
@@ -80,19 +82,26 @@ class RxReduxStore<A, S> {
8082
.asBroadcastStream(onCancel: (subscription) => subscription.cancel());
8183

8284
var currentState = initialState;
83-
final subscription = stateStream.listen(
84-
(newState) => currentState = newState,
85-
onError: errorHandler,
86-
);
85+
final subscriptions = <StreamSubscription<Object>>[
86+
stateStream.listen(
87+
(newState) => currentState = newState,
88+
onError: errorHandler,
89+
),
90+
];
8791

8892
return RxReduxStore._(
8993
actionController.add,
94+
(actions) => subscriptions.add(actions.listen(actionController.add)),
9095
() => currentState,
9196
stateStream,
9297
actionOutputController.stream,
9398
() async {
99+
if (subscriptions.length == 1) {
100+
await subscriptions[0].cancel();
101+
} else {
102+
await Future.wait(subscriptions.map((s) => s.cancel()));
103+
}
94104
await actionController.close();
95-
await subscription.cancel();
96105
},
97106
);
98107
}
@@ -169,6 +178,21 @@ class RxReduxStore<A, S> {
169178
/// store.dispatch(SubmitLogin());
170179
void dispatch(A action) => _dispatch(action);
171180

181+
/// Dispatch [Stream] of actions to store.
182+
///
183+
/// The [StreamSubscription] from listening [actionStream]
184+
/// will be cancelled when calling [dispose].
185+
/// Therefore, don't forget to call [dispose] to avoid memory leaks.
186+
///
187+
/// ### Example:
188+
///
189+
/// abstract class Action {}
190+
/// class LoadNextPageAction implements Action {}
191+
///
192+
/// Stream<LoadNextPageAction> loadNextPageActionStream;
193+
/// store.dispatchMany(loadNextPageActionStream);
194+
void dispatchMany(Stream<A> actionStream) => _dispatchMany(actionStream);
195+
172196
/// Dispose all resources.
173197
/// This method is typically called in `dispose` method of Flutter `State` object.
174198
///
@@ -183,3 +207,17 @@ class RxReduxStore<A, S> {
183207
/// }
184208
Future<void> dispose() => _dispose();
185209
}
210+
211+
/// Dispatch this action to [store].
212+
extension DispatchToExtension<A> on A {
213+
/// Dispatch this action to [store].
214+
/// See [RxReduxStore.dispatch].
215+
void dispatchTo<S>(RxReduxStore<A, S> store) => store.dispatch(this);
216+
}
217+
218+
/// /// Dispatch this actions [Stream] to [store].
219+
extension DispatchToStreamExtension<A> on Stream<A> {
220+
/// Dispatch this actions [Stream] to [store].
221+
/// See [RxReduxStore.dispatchMany].
222+
void dispatchTo<S>(RxReduxStore<A, S> store) => store.dispatchMany(this);
223+
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: rx_redux
22
description: Redux implementation based on Dart Stream, with the power of RxDart. Reactive redux store for Dart & Flutter.
3-
version: 2.1.0
3+
version: 2.1.1
44
author: Petrus Nguyễn Thái Học <[email protected]>
55
homepage: https://github.com/hoc081098/rx_redux.git
66
repository: https://github.com/hoc081098/rx_redux.git

test/store_test.dart

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:rx_redux/rx_redux.dart';
2+
import 'package:rxdart/rxdart.dart';
23
import 'package:test/test.dart';
34

45
enum Action {
@@ -334,5 +335,50 @@ void main() {
334335
..dispatch(1)
335336
..dispatch(2);
336337
});
338+
339+
test('Dispatch many', () async {
340+
{
341+
final store = RxReduxStore<int, int>(
342+
initialState: 0,
343+
sideEffects: [],
344+
reducer: (s, a) => s + a,
345+
);
346+
347+
store.dispatchMany(Rx.range(0, 100));
348+
await delay(200);
349+
350+
expect(store.state, 100 * 101 ~/ 2);
351+
await store.dispose();
352+
}
353+
354+
{
355+
final store = RxReduxStore<int, int>(
356+
initialState: 0,
357+
sideEffects: [],
358+
reducer: (s, a) => s + a,
359+
);
360+
361+
Rx.range(0, 100).dispatchTo(store);
362+
await delay(200);
363+
364+
expect(store.state, 100 * 101 ~/ 2);
365+
await store.dispose();
366+
}
367+
});
368+
369+
test('Action.dispatchTo extension method', () async {
370+
final store = RxReduxStore<int, int>(
371+
initialState: 0,
372+
sideEffects: [],
373+
reducer: (s, a) => s + a,
374+
);
375+
376+
1.dispatchTo(store);
377+
2.dispatchTo(store);
378+
await delay(100);
379+
380+
expect(store.state, 3);
381+
await store.dispose();
382+
});
337383
});
338384
}

0 commit comments

Comments
 (0)