将Redux-Persists的持久化accessToken获取到RTK查询API定义文件中-将再水化存储在组件层之外

ar5n3qh5  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(223)

我正在使用Redux工具包,Redux持久和RTK查询在我的项目。
我已经用Redux Toolkit和Redux Persists配置了存储。设法使用Redux Persists持久化数据。目前我可以使用useSelector挂钩将持久化数据放入我的组件层。
我有其他的API定义,这是由RTK查询完成的。我有一个文件与所有的API定义由RTK查询的createApi,baseQuery等函数完成。
我的“问题”是:

  • 在组件层中的存储初始化之前,我无法访问持久化数据。我可以访问数据,因为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延迟。
有什么问题尽管问。

dtcbnfnu

dtcbnfnu1#

到目前为止,我还没有找到一个解决方案。但我已经创建了在组件层检查令牌的功能,然后调用这些查询,在访问这些查询之前,我通过另一个切片中的组件副作用来调度令牌,这些副作用通常不会持久化。
还在等一个好的解决办法。
我尝试过使用redux-persistent storage调用选项,但也没有成功,因为我需要解析持久化数据。

ktca8awb

ktca8awb2#

我找到了一个访问非组件文件中存储的示例。
https://redux.js.org/faq/code-structure#how-can-i-use-the-redux-store-in-non-component-files
不确定如何使用RTK查询实现它,Redux保留reducer。

相关问题