redux-persist
redux-persist copied to clipboard
redux toolkit createAsyncThunk response not persisted
Description of issue
Scenario: User has loaded a page state with data (list of roles). Said user goes offline whilst in same page. He/she reloads same page. State is lost.
Question: How do I persist this state?
rolesSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { axiosCall } from "../../services/API";
// Define the initial state using that type
const initialState = {
roles: [],
loading: "",
};
// A function that accepts a Redux action type string and a callback function that should return a promise
export const getRoles = createAsyncThunk("roleSlice/getRoles", async (_, thunkAPI) => {
try {
// axios GET request (no credentials required)
const response = await axiosCall("roles?");
/**
* response.data => {"name:" "Super Admin", "active": true}
*/
return response.data;
} catch (err) {
// Use `err.response.data` as `action.payload` for a `rejected` action,
// by explicitly returning it using the `rejectWithValue()` utility
return thunkAPI.rejectWithValue(await err.response.data);
}
});
export const roleSlice = createSlice({
name: "roles",
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {},
extraReducers: (builder) => {
// A builder provides addCase, addMatcher and addDefaultCase functions that may be called to define what actions this reducer will handle
builder
// Add a case reducer to handle a single exact action type
.addCase(getRoles.pending, (state, action) => {
state.loading = "pending";
})
.addCase(getRoles.fulfilled, (state, action) => {
state.loading = "fulfilled";
state.roles.push(action.payload);
})
.addCase(getRoles.rejected, (state, action) => {
state.loading = "rejected";
});
},
});
export default roleSlice.reducer;
store.js
import { configureStore, combineReducers } from "@reduxjs/toolkit";
import { roleSlice } from "../app/features/roles/roleSlice";
import {
persistStore,
persistReducer,
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import storage from "redux-persist/lib/storage";
const persistConfig = {
key: "root",
storage,
};
const rootReducers = combineReducers({
roles: roleSlice.reducer,
});
const persistedReducer = persistReducer(persistConfig, rootReducers);
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
});
export const persistor = persistStore(store);
components/Roles.js
import React, { useState, useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { unwrapResult } from "@reduxjs/toolkit";
import { getRoles } from "../../app/features/roles/roleSlice";
import { XDCTable } from "../../customComponents/XDCTable"
const Roles = () => {
const dispatch = useDispatch();
const { roles } = useSelector((state) => state.roles);
const [data, setData] = useState([]);
const RenderTable = () => {
//return data.map((role) => {
return Object.keys(data).map((key) => {
const role = data[key];
return (
<tr key={key}>
<td>{role.name}</td>
<td>{role.status}</td>
</tr>
);
});
};
useEffect(() => {
const isOnline = window.navigator.onLine;
// true or false
if (isOnline) {
dispatch(getRoles())
.then(unwrapResult)
.then((res) => {
console.log(res);
if (!res.someErrorMessagefromAPI) {
setData(res);
} else {
//some fn
}
})
.catch((e) => {
console.log(e);
//some fn
});
} else {
setData(roles);
}
}, [dispatch]);
return (
<>
<XDCTable>
{RenderTable()}
</XDCTable>
</>
);
};
export default Roles;
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import * as serviceWorkerRegistration from "./serviceWorkerRegistration";
import reportWebVitals from "./reportWebVitals";
import App from "./App";
import { persistor, store } from "./app/store";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>
);
serviceWorkerRegistration.unregister();
reportWebVitals(console.log);
dependency information
react-redux: 8.0.2 @reduxjs/toolkit: 1.8.5 redux-persist: 6.0.0 redux: 4.2.0