Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save SugarDarius/224997f67b38849a04fb54777254caed to your computer and use it in GitHub Desktop.
Save SugarDarius/224997f67b38849a04fb54777254caed to your computer and use it in GitHub Desktop.
Sync React Reducer with session storage
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 { /* ... */ };
}
}
);
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];
};
@SugarDarius
Copy link
Author

Hey @malko42 !

It's corrected :)
Thanks for the comment:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment