Skip to content

Commit 6b305b0

Browse files
committed
Add stronger analysis, add LoadedAction, error handling
1 parent ed0177b commit 6b305b0

11 files changed

+93
-29
lines changed

packages/redux_persist/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## [0.5.0] - 2018-03-12
2+
3+
Breaking changes:
4+
* Change `persistor.load(store)` to `persistor.start(store)` for initial loading.
5+
* Change `LoadAction<T>` to `LoadedAction<T>`.
6+
* Add `LoadAction` (action dispatch to start loading).
7+
* Add `PersistorErrorAction` (action dispatched on save/load error).
8+
* Add `debug` persistor option, doesn't do anything yet.
9+
110
## [0.4.0] - 2018-03-10
211

312
* Decouple Flutter and Web into different packages.

packages/redux_persist/README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Storage Engines:
2323
See [Flutter example](https://github.com/Cretezy/redux_persist/tree/master/packages/redux_persist_flutter/example) for a full overview.
2424

2525
The library creates a middleware that saves on every action.
26-
It also loads on initial load and sets a `LoadAction` to your store.
26+
It also loads on initial load and sets a `LoadedAction` to your store.
2727

2828
### State Setup
2929

@@ -75,7 +75,7 @@ var store = new Store<AppState>(
7575
);
7676
7777
// Load state to store
78-
persistor.load(store);
78+
persistor.start(store);
7979
```
8080

8181
(the `key` param is used as a key of the save file name.
@@ -85,14 +85,14 @@ an instance of your state class, see the above example)
8585
### Load
8686

8787
In your reducer, you must add a check for the
88-
`LoadAction` action (with the generic type), like so:
88+
`LoadedAction` action (with the generic type), like so:
8989

9090
```dart
9191
class IncrementCounterAction {}
9292
9393
AppState reducer(state, action) {
9494
// !!!
95-
if (action is LoadAction<AppState>) {
95+
if (action is LoadedAction<AppState>) {
9696
return action.state ?? state; // Use existing state if null
9797
}
9898
// !!!
@@ -107,6 +107,13 @@ AppState reducer(state, action) {
107107
}
108108
```
109109

110+
### Optional Actions
111+
112+
You can also use the `LoadAction` or `PersistorErrorAction` to follow the lifecycle of the persistor.
113+
114+
* `LoadAction` is dispatched when the store is being loaded
115+
* `PersistorErrorAction` is dispatched when an error occurs on loading/saving
116+
110117
## Storage Engines
111118

112119
You can use the [Flutter](https://pub.dartlang.org/packages/redux_persist_flutter)
@@ -198,6 +205,19 @@ persistor = new Persistor<AppState>(
198205
);
199206
```
200207

208+
## Debug
209+
210+
`Persistor` has a `debug` option, which will eventually log debug information.
211+
212+
Use it like so:
213+
214+
```dart
215+
persistor = new Persistor<AppState>(
216+
// ...
217+
debug: true
218+
);
219+
```
220+
201221
## Features and bugs
202222

203223
Please file feature requests and bugs at the

packages/redux_persist/analysis_options.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
analyzer:
2-
strong-mode: true
2+
strong-mode:
3+
implicit-casts: false
4+
implicit-dynamic: false
35

46
linter:
57
rules:

packages/redux_persist/lib/redux_persist.dart

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,19 @@ abstract class StorageEngine {
1515
/// Decoder of state from [json] to <T>
1616
typedef T Decoder<T>(dynamic json);
1717

18-
/// Action being dispatched when loading state from disk.
19-
class LoadAction<T> {
18+
/// Action being dispatched when done loading the state from disk.
19+
class LoadedAction<T> {
2020
final T state;
2121

22-
LoadAction(this.state);
22+
LoadedAction(this.state);
2323
}
2424

25+
/// Action being dispatched to load the state from disk.
26+
class LoadAction<T> {}
27+
28+
/// Action being dispatched when error loading/saving to disk
29+
class PersistorErrorAction {}
30+
2531
/// Persistor class that saves/loads to/from disk.
2632
class Persistor<T> {
2733
final StorageEngine storage;
@@ -30,27 +36,51 @@ class Persistor<T> {
3036
final Transforms<T> transforms;
3137
final RawTransforms rawTransforms;
3238

33-
final StreamController loadStreamController =
39+
final StreamController<void> loadStreamController =
3440
new StreamController.broadcast();
3541

42+
final bool debug;
43+
3644
var loaded = false;
3745

38-
Persistor({this.storage, this.decoder, this.transforms, this.rawTransforms});
46+
Persistor({
47+
this.storage,
48+
this.decoder,
49+
this.transforms,
50+
this.rawTransforms,
51+
this.debug = false,
52+
});
3953

4054
/// Middleware used for Redux which saves on each action.
4155
Middleware createMiddleware() {
42-
return (Store store, action, NextDispatcher next) {
56+
return (Store store, dynamic action, NextDispatcher next) {
4357
next(action);
4458

45-
// Save on each action
46-
save(store.state);
59+
// Don't run load/save on error
60+
if (action is! PersistorErrorAction) {
61+
try {
62+
if (action is LoadAction<T>) {
63+
// Load and dispatch to state
64+
load().then((state) => store.dispatch(new LoadedAction<T>(state)));
65+
} else {
66+
// Save
67+
save(store.state as T);
68+
}
69+
} catch (error) {
70+
store.dispatch(new PersistorErrorAction());
71+
}
72+
}
4773
};
4874
}
4975

76+
void start(Store<T> store) {
77+
store.dispatch(new LoadAction<T>());
78+
}
79+
5080
/// Load state from disk and dispatch LoadAction to [store]
51-
Future<T> load(Store<T> store) async {
81+
Future<T> load() async {
5282
var json = await storage.load();
53-
var state;
83+
T state;
5484

5585
if (json != null) {
5686
rawTransforms?.onLoad?.forEach((transform) {
@@ -66,9 +96,6 @@ class Persistor<T> {
6696
});
6797
}
6898

69-
// Dispatch LoadAction to store
70-
store.dispatch(new LoadAction<T>(state));
71-
7299
// Emit
73100
loadStreamController.add(true);
74101
loaded = true;

packages/redux_persist/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: redux_persist
22
description: Persist Redux State
3-
version: 0.4.0
3+
version: 0.5.0
44
homepage: https://github.com/Cretezy/redux_persist/tree/master/packages/redux_persist
55
author: Charles Crete <[email protected]>
66

packages/redux_persist_flutter/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## [0.4.3] - 2018-03-12
2+
3+
* Fix load bug (loaded JSON instead of string)
4+
15
## [0.4.2] - 2018-03-10
26

37
* Breaking: Change PersistorGate `child` to `builder`.

packages/redux_persist_flutter/analysis_options.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
analyzer:
2-
strong-mode: true
2+
strong-mode:
3+
implicit-casts: false
4+
implicit-dynamic: false
35

46
linter:
57
rules:

packages/redux_persist_flutter/example/redux_persist_flutter_example.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class IncrementCounterAction {}
3030

3131
AppState reducer(state, action) {
3232
// Load to state
33-
if (action is LoadAction<AppState>) {
33+
if (action is LoadedAction<AppState>) {
3434
return action.state ?? state;
3535
}
3636

@@ -62,7 +62,7 @@ class MyApp extends StatelessWidget {
6262
);
6363

6464
// Load state and dispatch LoadAction
65-
persistor.load(store);
65+
persistor.start(store);
6666
}
6767

6868
@override

packages/redux_persist_flutter/lib/redux_persist_flutter.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
library redux_persist;
22

33
import 'dart:async';
4-
import 'dart:convert';
54
import 'dart:io';
65

76
import 'package:flutter/widgets.dart';
@@ -17,7 +16,7 @@ class FlutterStorage implements StorageEngine {
1716
final String key;
1817
StorageEngine locationEngine;
1918

20-
FlutterStorage(this.key, {location = FlutterSaveLocation.sharedPreference}) {
19+
FlutterStorage(this.key, {FlutterSaveLocation location = FlutterSaveLocation.sharedPreference}) {
2120
switch (location) {
2221
case FlutterSaveLocation.sharedPreference:
2322
locationEngine = new SharedPreferenceEngine(this.key);
@@ -47,8 +46,7 @@ class DocumentFileEngine implements StorageEngine {
4746

4847
if (await file.exists()) {
4948
// Read to json
50-
final string = await file.readAsString();
51-
return JSON.decode(string);
49+
return await file.readAsString();
5250
}
5351
return null;
5452
}
@@ -110,7 +108,7 @@ class PersistorGateState extends State<PersistorGate> {
110108

111109
// Listen for loads
112110
widget.persistor.loadStream.listen(
113-
(_) {
111+
(void _) {
114112
if (!_loaded) {
115113
setState(() {
116114
_loaded = true;

packages/redux_persist_flutter/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: redux_persist_flutter
22
description: Redux Persist Flutter Integration
3-
version: 0.4.2
3+
version: 0.4.3
44
homepage: https://github.com/Cretezy/redux_persist/tree/master/packages/redux_persist_flutter
55
author: Charles Crete <[email protected]>
66

packages/redux_persist_web/analysis_options.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
analyzer:
2-
strong-mode: true
2+
strong-mode:
3+
implicit-casts: false
4+
implicit-dynamic: false
35

46
linter:
57
rules:

0 commit comments

Comments
 (0)