Last active
June 2, 2020 11:55
-
-
Save SugarDarius/224997f67b38849a04fb54777254caed to your computer and use it in GitHub Desktop.
Sync React Reducer with session storage
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 * as React from 'react'; | |
import { useReducerSyncSessionStorage } from '../hooks'; | |
export const aStateAction = '@@my-reducer/A_STATE_ACTION'; | |
export type Action<A, P = {}> = { | |
type: A; | |
payload?: P; | |
} | |
export type ReducerState = { /*your state type */ }; | |
export type ReducerAction = Action<typeof aStateAction, { /* your payload type */ }>; | |
const initialState: ReducerState = { /* your initial state */ }; | |
const reducer: React.Reducer<ReducerState, ReducerAction> = (state: ReducerState, action: ReducerAction): ReducerState => { | |
// your reducer logic | |
}; | |
// without serializers | |
const [state, dispath] = useReducerSyncSessionStorage<ReducerState, ReducerAction>( | |
reducer, | |
initialState, | |
'session-storage-key', | |
); | |
// with serializers | |
export type SubReducerState = { /* your sub reducer state type */ }; | |
const [state, dispath] = useReducerSyncSessionStorage<ReducerState, ReducerAction, SubReducerState>( | |
reducer, | |
initialState, | |
'session-storage-key', | |
{ | |
write: (s: ReducerState): SubReducerState => { | |
return { /* ... */ }; | |
}, | |
read: (srs: SubReducerState): ReducerState => { | |
return { /* ... */ }; | |
} | |
} | |
); |
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 * as React from 'react'; | |
import { canUseDOM } from '../predicates'; | |
// Feel free to use localStorage instead of sessionStorage | |
export type UseReducerSyncSessionStorageSerializers<S, SS> = { | |
write: (s: S) => SS, | |
read: (ss: SS, initialState: S) => S | |
}; | |
export const useReducerSyncSessionStorage = <S, A, SS = {}>( | |
reducer: React.Reducer<S, A>, | |
initialState: S, | |
storageKey: string, | |
serializers?: | |
UseReducerSyncSessionStorageSerializers<S, SS> | |
): [ S, React.Dispatch<A> ] => { | |
const [state, dispatch] = React.useReducer<React.Reducer<S, A>, S>(reducer, initialState, (initialState: S): S => { | |
let cs: S = initialState; | |
if (canUseDOM) { | |
const sessionStorageValue = sessionStorage.getItem(storageKey); | |
if (sessionStorageValue !== null) { | |
cs = !!serializers ? serializers.read(JSON.parse(sessionStorageValue), initialState) : JSON.parse(sessionStorageValue); | |
} | |
} | |
return cs; | |
}); | |
React.useEffect(() => { | |
if (canUseDOM) { | |
try { | |
sessionStorage.setItem(storageKey, JSON.stringify(!!serializers ? serializers.write(state) : state )); | |
} | |
catch { | |
console.warn('[SessionStorage]::setItem has thrown an error'); | |
} | |
} | |
}, [storageKey, state]); | |
return [state, dispatch]; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey @malko42 !
It's corrected :)
Thanks for the comment:)