【发布时间】:2020-12-06 19:42:51
【问题描述】:
我是新手,目前正在尝试解决此错误。基本上我正在创建一个基于 axios 的 HttpAuthClient 并希望为每个请求添加访问令牌。当我尝试单击按钮时,我收到一个错误 - “未处理的拒绝(错误):无效的钩子调用。钩子只能是在函数组件的主体内部调用”。
组件
import React, { useState } from 'react';
import { HttpAuthClient } from "../HttpAuthClient/HttpAuthClient";
export const Content = () => {
const [pages, setPages] = useState(null);
const apiUrl = "https://xxxxx/";
const loadPages = async () => {
const response = await HttpAuthClient.get(apiUrl); //Error thrown
setPages(response.data);
console.log(pages);
};
return (
<button onClick={loadPages}>Load Pages</button>
)
};
HttpAuthClient
import Axios, { AxiosRequestConfig } from 'axios';
import { useAuthContext } from '../AuthContext/AuthContext';
const RequestHandler = (request: AxiosRequestConfig) => {
const { accessToken, isAuthenticated } = useAuthContext(); //Error thrown
if (isAuthenticated) {
request.headers['Authorization'] = `Bearer ${accessToken}`;
}
return request;
};
const HttpAuthClient = Axios.create();
HttpAuthClient.interceptors.request.use((request: AxiosRequestConfig) =>
RequestHandler(request)
);
export default HttpAuthClient;
AuthContext
import { createContext, useContext } from 'react';
import { IAuthContext } from '../../types/IAuthContext';
export const AuthContext = createContext<IAuthContext>({
user: null,
isAuthenticated: null,
accessToken: ''
});
export const useAuthContext = () => useContext(AuthContext);
身份验证提供者
import React, { useState, useEffect } from 'react';
import { useOktaAuth } from '@okta/okta-react';
import { AuthContext } from '../../components/AuthContext/AuthContext';
import { IAuthContext } from '../../types/IAuthContext';
import { IUserInfo } from '../../types/IUserInfo';
const AuthProvider = (props: any) => {
const { authState, authService } = useOktaAuth();
const [authContext, setAuthContext] = useState<IAuthContext>(
{} as IAuthContext
);
useEffect(() => {
if (!authState.isAuthenticated) {
setAuthContext({} as IAuthContext);
} else {
authService.getUser().then((info: IUserInfo) => {
setAuthContext({
accessToken: authState.accessToken,
isAuthenticated: authState.isAuthenticated,
user: info
});
});
}
}, [authState, authService]);
return (
<AuthContext.Provider value={authContext}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthProvider;
反应堆栈跟踪
react-dom.development.js:14724 Uncaught (in promise) Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.
at Object.throwInvalidHookError (react-dom.development.js:14724)
at useContext (react.development.js:1493)
at useAuthContext (AuthContext.tsx:10)
at RequestHandler (HttpAuthClient.tsx:5)
at HttpAuthClient.tsx:16
at async loadPages (Content.tsx:10)
【问题讨论】:
-
如果您
export default HttpAuthClient,则您的HttpAuthClient导入不正确。 -
你也可以分享堆栈跟踪吗?
-
@tmhao2005 - 查看堆栈跟踪更新。
-
这个错误听起来很直接。您正在 http 拦截器中尝试使用钩子
useContext:) 您只应该在组件的主体中调用它 -
是否可以通过 AuthProvider 向 http 拦截器添加令牌?我指的是shooksweb.com/react-okta-axios-interceptor,但不确定我是否可以在功能组件中做到这一点。任何代码 sn-p 都会有帮助吗?