我在我的项目中使用Redux Toolkit, Redux- persist和RTK查询。
我已经用Redux Toolkit和Redux Persist配置了存储。使用Redux persist保存数据。目前,我可以使用useSelector钩子将持久化的数据放入组件层。
我有其他API定义,这是由RTK查询完成的。我有一个文件,其中包含RTK查询的createApi, baseQuery等函数完成的所有API定义。
我"PROBLEM"这是:
- 我不能在组件层的存储初始化之前访问持久化数据,我可以访问数据,因为useSelector钩子正在使渲染等待,直到持久化数据被persistGate添加到存储
- 但是在同一个文件中,我调用那些查询函数钩子,这些钩子在另一个文件中定义,我需要持久的数据被重新水合。
// 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>
)
}
到目前为止,我还没有找到任何方法来获得持久化数据到我的API定义,因为我的API定义钩子总是调用持久化数据被导入到我的存储之前,这是由persistGate从应用程序延迟组件。
N:B:有什么问题请尽管问。
到目前为止,我还没有找到一个解决方案。但是我已经创建了在组件层检查令牌的功能,然后调用这些查询,在访问这些查询之前,我在另一个片中按组件副作用调度令牌,这通常不会被持久化。
仍在等待一个好的解决方案。
我已经尝试使用redux-persist存储调用选项,但也没有运气,因为那时我需要解析持久化的数据。
我发现了一个在非组件文件中访问store的例子。
https://redux.js.org/faq/code-structure how-can-i-use-the-redux-store-in-non-component-files
不知道如何用RTK查询实现,Redux持久化reducer