尝试配置私有 Axios 实例以在 Redux 切片中使用

问题描述 投票:0回答:1

因此,我正在为我的应用程序进行身份验证,我想要完成的任务是为我的 redux thunk 函数提供私有 Axios 实例,以便它们可以发出经过身份验证的请求。我遇到的主要问题是,我想向 Axios 实例配置提供访问令牌(存在于应用程序状态中),但这不起作用,因为它需要钩子,而 Redux 切片中不允许钩子。我尝试使用

store.getState()
直接访问状态,但是商店正在返回
undefined
,而且我也相信如果不使用钩子它就不会更新。我正在尝试提出一个解决方案,但我却一无所获。当然,出于多种原因,我想避免使用本地存储。也请不要建议 RTK-Query。我在下面提供了一些代码:

私有实例.ts

export const privateInstance = axios.create({
    baseURL: 'http://localhost:5000',
    headers: { 'Content-Type': 'application/json' },
    withCredentials: true
});

const refresh = useRefreshToken();

const accessToken = store?.getState().auth.userContext.accessToken;

// Request interceptor for API calls
privateInstance.interceptors.request.use(
    async config => {
        if (!config.headers['Authorization']) {
            config.headers['Authorization'] = `Bearer ${accessToken}`;
            config.headers['Accept'] = 'application/json';
            config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
        }
        return config;
    },
    error => {
        Promise.reject(error)
    });

// Response interceptor for API calls
privateInstance.interceptors.response.use((response) => {
    return response
}, async function (error) {
    const originalRequest = error.config;
    console.log(error)
    if (error.response.status === 403 && !originalRequest._retry) {
        originalRequest._retry = true;
        const access_token = await refresh();
        privateInstance.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
        return privateInstance(originalRequest);
    }
    return Promise.reject(error);
});

useRefreshToken.ts(

instance
只是配置了基本url的标准Axios实例`)

const useRefreshToken = () => {
    const refresh = async () => {
        try {
            await instance({
                url: '/auth/refresh',
                method: 'GET'
            }).then((res) => {
                return res.data.accessToken
            })
        } catch (e: any) {
            console.log(e)
        }
    }

    return refresh;
}

export default useRefreshToken;

示例Slice.ts

...
export const addToToDoListAsync = createAsyncThunk(
    "todoList/addToToDoListAsync",
    async (todoObject: ToDoObject) => {
        try {
            return privateInstance({
                url: '/todoList',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                data: JSON.stringify(todoObject)
            }).then((res) => {
                return res.data;
            })
        } catch (e: any) {
            console.log(e.response.data.error)
            return e;
        }

    }
)
...

请求失败并显示 403 禁止,因为当前实现未提供访问令牌。除了本地存储和 RTK 查询之外的任何帮助/想法将不胜感激。

reactjs typescript react-hooks axios react-redux
1个回答
0
投票

要在不使用 hooks 或 RTK-Query 的情况下解决此问题,您可以将访问令牌作为参数传递给 thunk 操作创建者。这样,您可以从组件内的 Redux 状态访问访问令牌,然后在分派 thunk 操作时将其作为参数传递。

以下是如何修改 addToToDoListAsync thunk 操作创建者以接受访问令牌作为参数:

javascript

export const addToToDoListAsync = createAsyncThunk(
    "todoList/addToToDoListAsync",
    async (payload: { todoObject: ToDoObject, accessToken: string }) => {
        const { todoObject, accessToken } = payload;
        try {
            return privateInstance({
                url: '/todoList',
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${accessToken}`
                },
                data: JSON.stringify(todoObject)
            }).then((res) => {
                return res.data;
            })
        } catch (e: any) {
            console.log(e.response.data.error)
            return e;
        }

    }
)

然后,在组件中分派 addToToDoListAsync 操作时,您可以将访问令牌作为参数传递:

import { addToToDoListAsync } from './exampleSlice';

// Assuming you have access to the access token in your component's props or state
const accessToken = 'your-access-token';

dispatch(addToToDoListAsync({ todoObject: yourTodoObject, accessToken }));

通过这种方式,您可以从组件内的 Redux 状态访问访问令牌,并将其传递给 thunk 操作创建者,从而允许您的私有 Axios 实例发出经过身份验证的请求,而无需依赖钩子或 RTK-Query。

© www.soinside.com 2019 - 2024. All rights reserved.