Skip to content

Instantly share code, notes, and snippets.

@keslert
Created September 24, 2020 17:31
Show Gist options
  • Save keslert/f0ef5248f2db354968c3c710a4adbe11 to your computer and use it in GitHub Desktop.
Save keslert/f0ef5248f2db354968c3c710a4adbe11 to your computer and use it in GitHub Desktop.
@reduxjs/toolkit + redux-persist + redux-undo
import { combineReducers } from 'redux';
import uiReducer from './slices/ui';
import documentsReducer, { undoRedoFilter as documentsFilter } from './slices/documents';
import elementsReducer, {
undoRedoGroupBy as elementsGroupBy,
undoRedoFilter as elementsFilter,
} from './slices/elements';
import personsReducer from './slices/persons';
import undoable from 'redux-undo';
const undoConfig = {
ignoreInitialState: true,
debug: true,
limit: 10,
};
const rootReducer = combineReducers({
ui: uiReducer,
documents: undoable(documentsReducer, {
...undoConfig,
filter: documentsFilter,
undoType: 'DOCUMENTS_UNDO',
redoType: 'DOCUMENTS_REDO',
}),
elements: undoable(elementsReducer, {
...undoConfig,
filter: elementsFilter,
groupBy: elementsGroupBy,
}),
persons: personsReducer,
});
export default rootReducer;
import { createTransform } from 'redux-persist';
import { newHistory } from 'redux-undo';
export const UndoTransform = createTransform(
// transform state on its way to being serialized and persisted.
(inboundState: any, key) => {
// Only store the present. We don't want to hydrate past or future.
return inboundState.present;
},
// transform state being rehydrated
(outboundState, key) => {
// Take the "present data" and turn it back into a history.
return newHistory([], outboundState, []);
},
// define which reducers this transform gets called for.
{ whitelist: ['elements', 'documents'] }
);
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import rootReducer from './reducer';
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
// import hardSet from 'redux-persist/lib/stateReconciler/hardSet';
import { persistStore, persistReducer } from 'redux-persist';
import { prepareEditor } from './utils/editor-utils';
import { UndoTransform } from './utils/store-utils';
const persistConfig = {
key: 'root',
version: 1,
storage,
transforms: [UndoTransform],
timeout: 0,
debug: true,
// hardSet should be used as the stateReconciler but it didn't work with typescript.
// The current implementation is just the function below, though.
stateReconciler: (state: any) => state,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
const store = configureStore({
reducer: persistedReducer,
middleware: getDefaultMiddleware({
immutableCheck: false,
serializableCheck: false,
}),
});
// @ts-ignore
const persistor = persistStore(store, { manualPersist: false }, () => {
const state = store.getState();
prepareEditor(state, store.dispatch);
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export { store, persistor };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment