I am using Redux Toolkit, Redux-Persist and RTK query in my project.
I have configured the store with Redux Toolkit and Redux Persist. Managed to persist data using Redux Persist. Currently I am able to get the persisted data into my component layer using useSelector hook.
I have other API definitions which is done by RTK query. I have a files with all the API definitions done by RTK query's createApi, baseQuery etc. functions.
My "PROBLEM" here is:
// Main App.js
const App = () => {
return (
<Provider store={store}>
<PersistGate persistor={persistor}>
<Route path="/orderlist" element={<OrdersList />} />
</PersistGate>
</Provider>
)
}
// Store Configuration
const persistConfig = {
key: 'root',
storage: storage,
blacklist: [],
whitelist: ['auth']
}
const reducers = {
[authSlice.name] : authSlice.reducer,
}
const rootReducer = combineReducers(reducers)
const persistedReducer = persistReducer(persistConfig, rootReducer)
export const token = (state) => state.persistedReducer
export const store =
configureStore({
reducer: {
persistedReducer,
[api.reducerPath]: api.reducer,
order: orderSlice.reducer,
[userApi.reducerPath]: userApi.reducer
// [orderSlice.name] : orderSlice.reducer,
// [api.reducerPath]: api.reducer,
// order: orderSlice.reducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
}
}).concat([
api.middleware,
userApi.middleware
]),
})
// Api Definitions - where I needed the persisted data
import { createApi, fetchBaseQuery, retry } from '@reduxjs/toolkit/query/react'
import { rootState } from '../store'
// Root state is not working here, this file execute the code before store intiatization
// I need the rehydrated state here
// Please check my store configuration
// const storeSubscription = store.getState()
// console.log(rootState)
// Create Our baseQuery Instance
const baseQuery = fetchBaseQuery({
baseUrl: 'http://34.229.141.62/api/v1/',
})
// console.log(baseQuery)
const baseQueryWithRetry = retry(baseQuery, { maxRetries: 1 })
export const userApi = createApi({
reducerPath: 'USER_API_REDUCER_KEY',
baseQuery: baseQueryWithRetry,
// prepareHeaders: (headers, { getState }) => {
// const token = getState().order.isToken
// console.log(token)
// // If we have a token set in state, let's assume that we should be passing it.
// if (token) {
// headers.set(`Bearer ${token}`)
// }
// return headers
// },
tagTypes: ['Orders'],
endpoints: builder => ({}),
serializeQueryArgs: ({ endpointName, queryArgs }) => endpointName
})
// Endpoint injections in create API
import { createSelector, createEntityAdapter } from "@reduxjs/toolkit";
import { userApi } from "./userApi";
const ordersAdapter = createEntityAdapter({
// selectId: (order) => order.id,
sortComparer: (a,b) => b._id.localeCompare(a._id)
})
const initialState = ordersAdapter.getInitialState()
export const extendedApiSlice = userApi.injectEndpoints({
endpoints: builder => ({
getOrders: builder.query({
query: () => ({
url: 'orders/userOrders',
}),
transformResponse: (responseData, meta, arg) => {
let i = 1
const loadedOrders = responseData.orders.map(order => {
if(!order?.id) order.id = i++
// console.log(order)
return order
})
return ordersAdapter.setAll(initialState, loadedOrders)
},
providesTags: (result, error, arg) => [
// { type: 'Orders', id: 'LIST' },
'Orders'
]
}),
deleteOrders: builder.mutation({
// query: ({id}) => ({
query: (body) => ({
// url: `orders/cancel/${id}`,
url: `orders/cancel/`,
method: 'POST',
body: body,
refetchOnMountOrArgChange: true,
invalidatesTags: (result, error, arg) => [
'Orders'
]
})
})
}),
})
// console.log(ordersAdapter)
export const {
useGetOrdersQuery,
useDeleteOrdersMutation
} = extendedApiSlice
// console.log(extendedApiSlice)
export const selectOrdersResult = extendedApiSlice.endpoints.getOrders.select()
export const deleteOrdersResult = extendedApiSlice.endpoints.deleteOrders.initiate()
export const selectdeleteOrderResult = extendedApiSlice.endpoints.deleteOrders.select()
// export const useDeleteOrdersMutation = extendedApiSlice.endpoints.deleteOrders.useMutation()
// console.log(deleteOrdersResult)
// console.log(selectdeleteOrderResult)
export const selectOrdersData = createSelector(
selectOrdersResult,
ordersResult => ordersResult.data
)
// console.log(selectOrdersData)
export const {
selectAll: selectAllOrders,
selectById: selectOrderById,
selectIds: selectOrderIds
} = ordersAdapter.getSelectors(state => selectOrdersData(state) ?? initialState)
// Component where I am calling those query hooks from create API
import { token } from "../../Servicepage/store";
import { useDispatch, useSelector } from "react-redux";
import { useGetOrdersQuery, useDeleteOrdersMutation, selectAllOrders, selectOrderById, selectOrderIds } from "../../Servicepage/services/userSlice";
import Button from "./Button";
import { addToken, resOrder, selectCount } from "../../Servicepage/services/orderSlice"
import { useEffect } from "react";
const OrdersList = () => {
const dispatch = useDispatch()
const authState = useSelector(token)
const Token = authState.auth.accessToken
// console.log(Token)
// dispatch(addToken({ isToken: false }))
useEffect(() => {
dispatch(addToken({ isToken: Token}))
}, [])
const completeOrderState = useSelector(selectCount)
// console.log(completeOrderState)
const {
isLoading,
isSuccess,
refetch,
isError,
error
} = useGetOrdersQuery()
const orderIds = useSelector(selectOrderIds)
const orderIdz = useSelector((state) => selectOrderById(state, 1))
const orderAll = useSelector(selectAllOrders)
const [deletePost] = useDeleteOrdersMutation()
let content;
if (isLoading) {
content = <p>"Loading..."</p>
} else if (isSuccess) {
// console.log(orderIds)
// console.log(orderIdz)
console.log(orderAll)
// deletePost({ id: 'JBCS000001' })
content = orderAll.map((orders, indx) => {
return (
<div key={indx}>
<p><strong>Order List</strong></p>
<p>{orders.id}</p>
<p>Total Amount: {orders.totalAmount}</p>
<p>Email: {orders.email} </p>
<p>OrderId: {orders.orderId} </p>
<p>Status: {orders.status}</p>
<Button orderID={orders.orderId} />
</div>
)
})
}
return (
<div>
{content}
</div>
)
}
So far I haven't been found any way to get the persisted data into my API definitions because my API definitions hooks are always calling before persisted data being imported into my store which is delayed in component by persistGate from App.
N:B: Please feel free to ask any question.
So far I have not found a solution in my opinion. But I have created the functionality checking the Token in component layer and then calling those query, and before accessing those queries, I am dispatching the token by component side effects in another slice, which do not get persisted usually.
Still waiting for a good solution.
I have tried to use redux-persist storage calling option but no luck for that one too, because then I need to parse the persisted data.