-
-
Save awendland/baa6fefb552356865a65 to your computer and use it in GitHub Desktop.
localStorage sync with redux and TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { reduxStorageReducer, ReduxStorage } from 'reduxStorage'; | |
import myReducer from './myReducer'; | |
function compose(...reducers) { | |
return (state, action) => { | |
return reducers.reduce((reducedState, reducer) => { | |
return reducer(reducedState, action); | |
}, state); | |
}; | |
} | |
const finalReducer = compose(myReducer, reduxStorageReducer); | |
const storage = new ReduxStorage('redux'); | |
const redux = createRedux(finalReducer, storage.load()); | |
storage.connect(redux); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import WebStorage from 'WebStorage'; | |
const STORAGE_SYNC = 'STORAGE_SYNC'; | |
export const actions = { STORAGE_SYNC }; | |
export function syncActionCreator(state) { | |
return { | |
type: STORAGE_SYNC, | |
synced: state, | |
}; | |
} | |
export function reduxStorageReducer(state, action) { | |
if (action.type === STORAGE_SYNC) { | |
// Depends on state being an object|null|undefined | |
return Object.assign({}, state, action.synced); | |
} else { | |
return state; | |
} | |
} | |
export class ReduxStorage extends WebStorage { | |
connect(redux, actionCreator = syncActionCreator, listen = true) { | |
redux.subscribe(() => this.save(redux.getState())); | |
if (listen) { | |
this.listen(() => redux.dispatch(actionCreator(this.load()))); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class WebStorage { | |
private key: string; | |
private storageArea: Storage; | |
constructor(key: string, storageArea = window.localStorage) { | |
this.key = key; | |
this.storageArea = storageArea; | |
} | |
load<T>(defaultValue?: T): T { | |
const serialized = this.storageArea.getItem(this.key); | |
return serialized === null ? defaultValue : this.deserialize(serialized); | |
} | |
/** | |
* Save a JSON serializable object into the data store | |
* | |
* @param {any} data [description] | |
*/ | |
save(data: any): void { | |
if (data === undefined) { | |
this.storageArea.removeItem(this.key); | |
} else { | |
this.storageArea.setItem(this.key, this.serialize(data)); | |
} | |
} | |
/** | |
* Clear this storage section from the storage area | |
*/ | |
clear(): void { | |
this.storageArea.removeItem(this.key); | |
} | |
private serialize(value) { | |
return JSON.stringify(value); | |
} | |
private deserialize(value) { | |
return JSON.parse(value); | |
} | |
/** | |
* Listen for changes in the storage area that occur from other pages | |
* on the domain | |
* | |
* @param {Function} callback Single parameter is a StorageEvent | |
* @return {Function} Function to remove the listener | |
*/ | |
listen(callback: (StorageEvent) => void): () => void { | |
const handler = (e) => { | |
if (e.key === this.key && e.storageArea === this.storageArea) { | |
callback(e); | |
} | |
}; | |
window.addEventListener('storage', handler); | |
return () => window.removeEventListener('storage', handler); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment