Preact+React-Query中调用useAuth0获取Auth0 Access Token报错求助
问题分析与解决方案
错误原因
你遇到的Cannot read properties of null (reading 'context')错误,核心是违反了React/Preact的Hook调用规则:Hook只能在组件或自定义Hook的顶层调用,不能在普通异步函数(比如你的apiGet)内部调用useAuth0。这种情况下,Hook无法正确关联到组件上下文,导致上下文查找失败。
解决方案(满足Token逻辑封装需求)
方案一:抽离Token获取Hook,传递给API函数
先把Token获取逻辑封装成自定义Hook,再将Token获取方法传递给API函数:
- 封装Token获取Hook
export const useAuthToken = () => { const { getAccessTokenSilently } = useAuth0(); // 返回一个异步函数,用于获取Token return async () => getAccessTokenSilently(); };
- 修改API函数,接收Token获取方法
export const apiGet = async (getToken) => { const token = await getToken(); const response = await axios.get("[API URL]", { headers: { Authorization: `Bearer ${token}` } }); return response.data; };
- 在数据Hook中使用
export const useGetData = () => { const getToken = useAuthToken(); return useQuery(["test"], () => apiGet(getToken)); };
方案二:用Axios拦截器全局处理Token注入(更优雅)
通过自定义Hook创建带拦截器的Axios实例,自动在请求头添加Token,无需每个API调用手动处理:
- 创建带Auth拦截的Axios实例Hook
import axios from 'axios'; import { useAuth0 } from '@auth0/auth0-react'; export const useApiClient = () => { const { getAccessTokenSilently } = useAuth0(); const apiClient = axios.create({ baseURL: "[API BASE URL]" // 替换为你的API基础地址 }); // 请求拦截器:自动注入Token apiClient.interceptors.request.use(async (config) => { const token = await getAccessTokenSilently(); config.headers.Authorization = `Bearer ${token}`; return config; }); return apiClient; };
- 简化API调用
// 可以直接在数据Hook中使用apiClient,无需单独的apiGet函数 export const useGetData = () => { const apiClient = useApiClient(); return useQuery(["test"], async () => { const response = await apiClient.get("[API ENDPOINT]"); // 替换为具体接口路径 return response.data; }); };
如果需要复用API逻辑,也可以封装成方法:
// 封装API方法 export const createApi = (apiClient) => ({ getTestData: async () => { const res = await apiClient.get("[API ENDPOINT]"); return res.data; }, // 其他接口方法... postData: async (payload) => { const res = await apiClient.post("[POST ENDPOINT]", payload); return res.data; } }); // 在数据Hook中使用 export const useGetData = () => { const apiClient = useApiClient(); const { getTestData } = createApi(apiClient); return useQuery(["test"], getTestData); };
核心思路
所有需要调用Hook的逻辑必须放在组件或自定义Hook的顶层,然后将获取到的能力(Token获取方法、配置好的请求实例)传递给普通的API函数,既实现了Token逻辑的封装,又严格遵守Hook规则。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

