I'm having a problem getting Redux-Persist to work and hoping to get some pointers if I've done something wrong.
Here is my Store.js
import { configureStore, getDefaultMiddleware } from "@reduxjs/toolkit";
import { persistStore, persistReducer } from "redux-persist";
import AsyncStorage from "@react-native-async-storage/async-storage";
import authReducer from "./slices/AuthSlice";
import expensesReducer from "./slices/ExpensesSlice";
import devToolsEnhancer from "redux-devtools-expo-dev-plugin";
const persistConfig = {
key: "primary",
keyPrefix: "",
storage: AsyncStorage,
whitelist: ["auth"], // Add other slices you want to persist
stateReconciler: (inboundState, originalState, reducedState, { debug }) => {
if (debug) {
console.log("Rehydrating state:", inboundState);
}
// Log the actual state data
console.log("Inbound state data:", inboundState);
console.log("Original state data:", originalState);
console.log("Reduced state data:", reducedState);
return { ...reducedState, ...inboundState };
},
};
const persistedReducer = persistReducer(persistConfig, authReducer);
export const store = configureStore({
reducer: {
auth: persistedReducer,
expenses: expensesReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ["persist/PERSIST", "persist/REHYDRATE"],
},
}),
devTools: false,
enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers().concat(devToolsEnhancer()),
});
store.subscribe(() => {
console.log("State after dispatch: ", store.getState());
});
export const persistor = persistStore(store);
persistor.subscribe(() => {
console.log("Persistor state: ", persistor.getState());
});
console.log("Store configured");
This is the slice I'm trying to persist:
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
access: "denied",
access_token: "",
expiry: "",
refresh_token: "",
user_id: "",
currency: "SGD",
};
export const AuthSlice = createSlice({
name: "auth",
initialState,
reducers: {
updateTokens: (state, action) => {
console.log("updateTokens action dispatched");
state.access = action.payload.access;
state.access_token = action.payload.access_token;
state.expiry = action.payload.expiry;
state.refresh_token = action.payload.refresh_token;
state.user_id = action.payload.user_id;
},
logout: (state, action) => {
console.log("logout action dispatched");
state.access = "denied";
state.access_token = "";
state.expiry = "";
state.refresh_token = "";
state.user_id = "";
},
},
});
export const { updateTokens, logout } = AuthSlice.actions;
export default AuthSlice.reducer;
When I login to the app I can see the state updated and the app successfully logs in.
When I close the app and reopen it it rehydrates the state by the looks of it but only with the initialState, this leads me to believe that the persisted state is not being updated when the state changes at login.
You are currently already only persisting the auth reducer
import authReducer from "./slices/AuthSlice";
const persistConfig = {
key: "primary",
keyPrefix: "",
storage: AsyncStorage,
whitelist: ["auth"], // Add other slices you want to persist
...
};
const persistedReducer = persistReducer(persistConfig, authReducer);
so when whitelisting "auth"
you are effectively configuring Redux-Persist to persist only the "auth"
reducer/property of the authReducer
. Since there is no state.auth.auth
reducer/state/property to persist, nothing is persisted.
Either omit the whitelist: ["auth"]
part of the configuration and simply persist the entire authReducer
state:
import authReducer from "./slices/AuthSlice";
const persistConfig = {
key: "primary",
keyPrefix: "",
storage: AsyncStorage,
...
};
const persistedAuthReducer = persistReducer(persistConfig, authReducer);
export const store = configureStore({
reducer: {
auth: persistedAuthReducer,
expenses: expensesReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ["persist/PERSIST", "persist/REHYDRATE"],
},
}),
devTools: false,
enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers().concat(devToolsEnhancer()),
});
...
export const persistor = persistStore(store);
Or keep the whitelist: ["auth"]
and combine your reducers such that there is an auth
reducer state to persist:
import {
configureStore,
combineReducers,
getDefaultMiddleware
} from "@reduxjs/toolkit";
import authReducer from "./slices/AuthSlice";
const persistConfig = {
key: "primary",
keyPrefix: "",
storage: AsyncStorage,
whitelist: ["auth"],
...
};
const rootReducer = combineReducers({
auth: authReducer,
expenses: expensesReducer,
});
const persistedRootReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedRootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: ["persist/PERSIST", "persist/REHYDRATE"],
},
}),
devTools: false,
enhancers: (getDefaultEnhancers) =>
getDefaultEnhancers().concat(devToolsEnhancer()),
});
...
export const persistor = persistStore(store);