I have a state in my redux store for user, it has a handful of fields including token. If my local storage is fresh, I can login to my app, have the user info update in redux, and all is dandy.
We are using redux-persist and redux-toolkit which I hope is not the issue. We have much more than this user in our state, but this is all that we need to keep session to session, so it'd be a shame to have to rewrite everything :/
However on logout, when I try to clear the user information, my localstorage doesn't update, and then Rehydrate grabs the user info we used to have, and puts it back in the store, making the call effectively do nothing.
store.js
import { combineReducers } from 'redux';
import { configureStore } from '@reduxjs/toolkit';
import alertReducer from './alertSlice';
import loaderReducer from './loaderSlice';
import notificationReducer from './notificationSlice';
import userReducer from './userSlice';
import { persistStore, createMigrate, persistReducer } from 'redux-persist';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import storage from 'redux-persist/lib/storage'; // defaults to localStorage for web
const rootReducer = combineReducers({
alert: alertReducer,
loader: loaderReducer,
notification: notificationReducer,
user: userReducer,
});
const migrations = {
0: (state) => {
// initial state, do not change -GL
return {
alert: {
alerts: [],
},
loader: {
loader: {
show: false,
message: '',
},
},
notification: {
notifications: [],
priority: '',
},
user: {
subscription_expired: true,
subscription_expires_date: null,
payment_failed: false,
}
}
},
1: (state) => {
return {
...state,
user: {
...state.user,
token: null,
userInitial: null,
}
}
}
}
const persistConfig = {
key: 'root',
storage,
version: 1,
whitelist: ['user'],
migrate: createMigrate(migrations, { debug: false }),
stateReconciler: autoMergeLevel2
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export default () => {
const store = configureStore({
reducer: persistedReducer,
});
const persistor = persistStore(store);
return { store, persistor };
};
userSlice.js
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
subscription_expired: true,
subscription_expires_date: null,
payment_failed: false,
token: null,
userInitial: null,
};
const userSlice = createSlice({
name: 'user',
initialState: initialState,
reducers: {
updateUser: (state, action) => {
const { payload } = action;
state.subscription_expired = payload.subscription_expired;
state.subscription_expires_date = payload.subscription_expires_date;
state.payment_failed = payload.payment_failed;
state.token = payload.access_token;
},
clearUser: (state, action) => {
console.log('clearing user');
state = initialState;
},
storeToken: (state, action) => {
state.token = action.payload;
},
clearToken: (state, action) => {
state.token = null;
},
},
});
export const { updateUser, clearUser, storeToken, clearToken } = userSlice.actions;
const { reducer } = userSlice;
export default reducer;
Logout function in my functional component logOut here is just helper that makes a call to my api
const handleLogout = () => {
logOut()
.then(() => {
dispatch(clearUser());
navigate('/');
});
};
I've tried autoLevelMerge1. I've tried writing my slices to return new objects instead of the imer fake mutations seen here. I've not been able to find a lot of information on how these two interact but the examples I did find seem to suggest this setup is correct.
I'm expecting the user to be set back to initial state when I dispatch clear user, and I expect localstorage to reflect that.