You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Redux Thunk与Axios实例中获取useAuth0钩子数据

问题描述

项目基于Redux、@reduxjs/toolkit、react-redux实现状态管理,通过redux-thunk结合axios发起HTTP请求,同时集成Auth0处理用户注册与登录。当前核心问题是:非React组件/钩子的axios实例文件和thunk文件无法使用@auth0/auth0-react的useAuth0钩子,但需要在axios实例中访问getAccessTokenSilently、isAuthenticated、loginWithRedirect等Auth0数据来动态更新请求授权令牌,且希望避免在每个调用thunk的React组件中重复执行Auth0检查逻辑。

解决方案:通过Redux Thunk注入Auth0实例

核心思路是在根组件中获取Auth0实例,将其作为额外参数传递给Redux Thunk中间件,使thunk和axios实例能直接访问Auth0方法,无需在组件层重复处理认证逻辑。

步骤1:修改根组件,传递Auth0实例给Store

在根组件中通过useAuth0获取实例,创建Store时将其传入:

import React from 'react';
import { Provider } from 'react-redux';
import { useAuth0 } from '@auth0/auth0-react';
import createStore from '../store/createStore';

const App = () => {
  const auth0 = useAuth0();
  const store = createStore(undefined, auth0);

  return (
    <Provider store={store}>
      {/* 应用业务组件 */}
    </Provider>
  );
};
export default App;

步骤2:配置Store,为Thunk注入Auth0实例

修改createStore函数,将Auth0实例作为extraArgument传递给thunk中间件:

/* eslint-disable import/no-cycle */
import { configureStore } from '@reduxjs/toolkit';
import thunk from 'redux-thunk';

const createStore = (initialState?: any, auth0?: any) => {
  return configureStore({
    reducer: {
      // 项目reducer定义
    },
    middleware: [thunk.withExtraArgument(auth0)],
    preloadedState: initialState,
  });
};

export default createStore;

步骤3:改造Axios实例,接收Auth0参数

将axios实例改为接收Auth0实例的函数,在内部处理令牌逻辑:

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { getAuthSignature } from '../utils/auth';

export const API_URL = process.env.API_HOST;

const axiosInstance = async <T = any>(requestConfig: AxiosRequestConfig, auth0: any): Promise<AxiosResponse<T>> => {
  const { token } = await getAuthSignature();
  const { getAccessTokenSilently, isAuthenticated, loginWithRedirect } = auth0;

  let accessToken = token;

  // 处理Auth0令牌更新逻辑
  if (auth0) {
    if (isAuthenticated) {
      try {
        accessToken = await getAccessTokenSilently({ audience: '你的API Audience' });
      } catch (err) {
        loginWithRedirect();
        throw new Error('获取Auth0访问令牌失败');
      }
    } else {
      loginWithRedirect();
      throw new Error('用户未认证');
    }
  }

  if (!accessToken) {
    throw {
      title: '错误',
      message: '缺少认证令牌',
      success: false,
    };
  }

  try {
    return await axios({
      ...requestConfig,
      headers: {
        ...requestConfig.headers,
        authorization: `Bearer ${accessToken}`,
      },
    });
  } catch (error: any) {
    if (error.response?.status && [401, 403].includes(error.response.status)) {
      loginWithRedirect();
    }

    const contentType = error?.response?.headers?.['content-type'];
    const isHTMLRes = contentType && contentType.indexOf('text/html') !== -1;

    throw {
      status: error?.response?.status,
      statusText: error?.response?.statusText,
      errorMessage: isHTMLRes && error?.response?.text ? await error.response.text() : undefined,
      error,
    };
  }
};

export default axiosInstance;

步骤4:更新Thunk Action,从额外参数获取Auth0实例

Thunk函数可通过第三个参数接收注入的Auth0实例,传递给axios实例:

import axiosInstance, { API_URL } from '../../services/axios';
import { Result } from '../../types/test';
import { setResults, setResultsLoading, setTableLoading } from './test.slice';

const getResults = () => async (dispatch, getState, auth0) => {
  dispatch(setTableLoading(true));

  try {
    const result = await axiosInstance<Result[]>(
      {
        method: 'GET',
        url: `${API_URL}/test`,
      },
      auth0
    );
    dispatch(setResults(result.data));
  } catch (err: any) {
    console.error(err);
  } finally {
    dispatch(setResultsLoading(false));
    dispatch(setTableLoading(false));
  }
};

export default getResults;

步骤5:组件调用无需修改

组件依然直接dispatch thunk即可,认证逻辑已在底层封装:

import React, { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import getResults from '../../reducers/test/test.thunk';

const TestComponent = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(getResults());
  }, [dispatch]);

  return (
    {/* 组件UI内容 */}
  );
};

export default TestComponent;

内容的提问来源于stack exchange,提问作者mcclosa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:10:29