ReactJS使用Auth0抽离接口逻辑时报Invalid hook call错误
报错原因
你现在的代码踩了React Hook规则的两个核心坑,UseAPI根本没有被React识别为合法的函数组件,自然不能在里面调用Hook:
- 合法的React函数组件必须返回可渲染内容(JSX、null、字符串、Fragment等),你的
UseAPI函数没有任何return语句,执行完默认返回undefined,React不会把它当作组件处理。 - 退一步说,就算你给
UseAPI加了返回值,如果你是在按钮的onClick回调里直接写UseAPI({endpoint: "xxx"})调用它,本质是把它当普通JS函数在事件回调里执行,完全违反Hook的调用要求:Hook只能在React函数组件/自定义Hook的顶层作用域调用,不能放在事件回调、条件判断、普通函数里执行。 - 额外提一句,你写的fetch逻辑里还有个模板字符串错误:URL拼接写的是
${serverUrl}/{props.endpoint},少了插值需要的$,就算Hook不报错,请求路径也会拼错。
修复方法
抽离接口请求逻辑最合理的方式是写自定义Hook,不需要额外写组件,步骤如下:
- 修改
api_funcs.js的代码,遵循自定义Hook的命名规范(以use开头),把请求方法暴露出来:import { useAuth0 } from '@auth0/auth0-react'; export const useApi = () => { const serverUrl = process.env.REACT_APP_SERVER_URL; const { getAccessTokenSilently } = useAuth0(); const callEndpoint = async (endpoint) => { try { const token = await getAccessTokenSilently(); console.log('request endpoint:', `${serverUrl}/${endpoint}`); const response = await fetch( `${serverUrl}/${endpoint}`, { headers: { Authorization: `Bearer ${token}`, }, } ); const responseData = await response.json(); console.log(responseData.message); return responseData; } catch (error) { console.log(error.message); throw error; } }; return { callEndpoint }; }; - 在
app.js的组件顶层作用域调用这个自定义Hook,拿到请求方法后再绑定到按钮事件上:import { useApi } from './api_funcs'; function App() { // 注意:Hook必须写在组件顶层,不能放在onClick、条件判断内部 const { callEndpoint } = useApi(); // 其他原有组件逻辑... return ( {/* 其他原有渲染内容 */} <Button variant="outline-primary" onClick={() => callEndpoint("get_timestamp_public")} > Fetch Public Data </Button> {/* 其他原有渲染内容 */} ) }
如果你一定要把
UseAPI写成函数组件,就必须给它加合法的返回值,并且以<UseAPI endpoint="get_timestamp_public" />的组件形式写在JSX渲染树里,不能在事件回调里直接当普通函数调用。但对请求逻辑抽离这个场景来说,用自定义Hook是最轻量合理的方案,没必要多套一层无意义的组件。
内容的提问来源于stack exchange,提问作者user1357015
相关产品推荐
相关产品推荐

