在普通函数中调用React Hook是否合规?能否忽略对应ESLint警告?
能否忽略该警告?
绝对不建议忽略该警告,原因如下:
- React Hook有严格的调用规则,只能在React函数组件、自定义Hook的顶层执行。普通工具函数
checkToken的执行上下文不属于React的渲染周期,此时调用useGeneralContext根本无法获取到正确的Context上下文,轻则返回undefined,重则直接触发运行时错误,ESLint的提示不是无意义的格式校验,是在提前避免运行时报错。 - 你当前代码里的
setUserSessionExpired实际上也没有被调用,就算后续补上调用逻辑,在普通函数里调用也无法触发Context关联的组件重渲染,状态更新不会生效。
可行的修复方案
方案1:将状态更新函数作为参数传递
你可以在调用call方法的组件内先获取Context的方法,再逐层传入:
// 组件内调用call的地方 const { setUserSessionExpired } = useGeneralContext() // 调用时传入状态更新函数 const res = await call('/api/xxx', token, data, setUserSessionExpired)
修改call和checkToken的定义,接收该参数:
const checkToken = (data, setUserSessionExpired) => { if (data.status === 'fail' && data.message === 'Sessione scaduta') { setUserSessionExpired(true) // 可以补上你遗漏的状态更新逻辑 window.location.href = '/auth/login?session=expired'; localStorage.removeItem('jwt'); } return data; }; export const call = async (url, token, data, setUserSessionExpired) => { // 原有请求逻辑不变 const dataReturned = await fetch(url, { method: 'PUT', headers: { Accept: 'application/json', 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify(data), }) .then((response) => { return response.json(); }) .catch((err) => { return { status: 'fail', message: 'API CALL ERROR', error: err.message }; }); return checkToken(dataReturned, setUserSessionExpired); };
方案2:封装请求为自定义Hook
如果不想每次调用都传参数,可以把请求方法封装成自定义Hook:
export function useRequest() { const { setUserSessionExpired } = useGeneralContext() const call = async (url, token, data) => { const dataReturned = await fetch(url, { method: 'PUT', headers: { Accept: 'application/json', 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify(data), }) .then((response) => { return response.json(); }) .catch((err) => { return { status: 'fail', message: 'API CALL ERROR', error: err.message }; }); if (dataReturned.status === 'fail' && dataReturned.message === 'Sessione scaduta') { setUserSessionExpired(true) window.location.href = '/auth/login?session=expired'; localStorage.removeItem('jwt'); } return dataReturned } return { call } }
组件内使用方式:
const { call } = useRequest() // 直接调用call即可,不需要额外传状态更新方法 const res = await call('/api/xxx', token, data)
内容的提问来源于stack exchange,提问作者Singh
相关产品推荐
相关产品推荐

