将 Redux-Persists 的持久化访问令牌获取到 RTK 查询 API 定义文件中 - 存储解除冻结,而不是在组件层中



我在我的项目中使用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

相关内容

最新更新