@@ -11,21 +11,21 @@ const isSupported = !!(window && window.localStorage);
1111 */
1212const syncedReducers = [ ] ;
1313
14- const LOAD = '@@sync-reducer/init' ;
15-
1614/**
17- * Get the type of the action.
18- * @param {string } name
15+ * Used action types.
16+ * @readonly
17+ * @enum {string}
1918 */
20- function getActionType ( name ) {
21- return `@@sync-reducer/sync/${ name } ` ;
19+ export const ActionTypes = {
20+ INIT : '@@redux-sync-reducer/INIT' ,
21+ UPDATE : '@@redux-sync-reducer/UPDATE' ,
2222}
2323
2424/**
2525 * Get the key used in localStorage.
2626 */
2727function getKeyName ( name ) {
28- return `@@sync-reducer/${ name } ` ;
28+ return `@@redux- sync-reducer/${ name } ` ;
2929}
3030
3131/**
@@ -48,29 +48,28 @@ function sync(name, data) {
4848 */
4949export function syncedReducer ( reducer , config = { } ) {
5050 const name = config . name || reducer . toString ( ) ;
51- const actionType = getActionType ( name ) ;
51+ syncedReducers . push ( name ) ;
5252
5353 let isLoaded = ! ! config . skipLoading ;
5454
55- syncedReducers . push ( name ) ;
56-
5755 return ( state , action = { } , ...slices ) => {
58- switch ( action . type ) {
59- case actionType :
60- return config . skipReducer ? action . payload : reducer ( action . payload , action , ...slices ) ;
61- case LOAD :
62- if ( ! isLoaded ) {
63- isLoaded = true ;
64- return isSupported
65- ? JSON . parse ( localStorage . getItem ( getKeyName ( name ) ) ) || state
66- : state ;
67- }
68- // fallthrough to default case if the state is already loaded
69- default :
70- return isLoaded
71- ? sync ( name , reducer ( state , action , ...slices ) )
72- : reducer ( state , action , ...slices ) ;
56+ if ( action . type === ActionTypes . UPDATE && action . name === name ) {
57+ return config . skipReducer
58+ ? action . payload
59+ : reducer ( action . payload , action , ...slices ) ;
7360 }
61+
62+ if ( action . type === ActionTypes . INIT && ! isLoaded ) {
63+ isLoaded = true ;
64+
65+ return isSupported
66+ ? JSON . parse ( localStorage . getItem ( getKeyName ( name ) ) ) || state
67+ : state ;
68+ }
69+
70+ return isLoaded
71+ ? sync ( name , reducer ( state , action , ...slices ) )
72+ : reducer ( state , action , ...slices ) ;
7473 }
7574}
7675
@@ -81,9 +80,13 @@ export const syncMiddleware = store => {
8180 isSupported && window . addEventListener ( 'storage' , e => {
8281 syncedReducers . some ( name => {
8382 if ( e . key === getKeyName ( name ) ) {
83+ // don't use e.newValue because it doesn't work in IE
84+ const payload = JSON . parse ( localStorage . getItem ( e . key ) ) ;
85+
8486 store . dispatch ( {
85- type : getActionType ( name ) ,
86- payload : JSON . parse ( e . newValue )
87+ type : ActionTypes . UPDATE ,
88+ payload,
89+ name
8790 } ) ;
8891
8992 return true ;
@@ -94,7 +97,7 @@ export const syncMiddleware = store => {
9497 } ) ;
9598
9699 // load all existing states from localStorage
97- store . dispatch ( { type : LOAD } ) ;
100+ store . dispatch ( { type : ActionTypes . INIT } ) ;
98101
99102 return next => action => next ( action ) ;
100103}
0 commit comments