React自定义SWR条件请求钩子写法是否正确?能否避免不必要接口调用?
结论
你的封装基本可以解决重复请求的问题,但存在冗余代码和潜在的错误点,可以进一步优化。
为什么现有封装能解决重复请求问题
- 你正确使用了SWR的条件请求特性:当传入
useSWR的第一个参数为null时,SWR会直接跳过请求逻辑,不会发起接口调用。 - 你主动关闭了
revalidateOnFocus、revalidateIfStale两个默认会触发自动重新验证的配置项,避免了窗口聚焦、数据过期等场景下的非预期额外请求。 - 只有当你调用
useShouldMakeCallToApiUser传入参数为true时,才会把/api/user地址传给SWR触发请求,确实只会在引入钩子的组件加载时触发一次请求,不会出现无意义的重复调用。
现有代码的可优化点
- 存在冗余的状态和嵌套钩子定义:你当前代码里的
useState、useEffect以及嵌套的useUser函数都是没有必要的,直接扁平化处理即可,不会影响原有功能,还能避免额外的重渲染开销。 - fetcher的catch分支存在报错风险:当请求出错且没有
err.response(比如跨域、网络中断)时,你写的return await res.json()中的res是未定义的,会触发二次错误。 - 原代码中给非异步的
new Error加await属于无效写法,没有实际作用可以直接移除。
优化后的代码参考
hooks.js 文件
import useSWR from 'swr'; import axios from 'axios' async function getUser(url) { try { const res = await axios.get(url); return res; } catch (err) { console.log("err ", err); if (err.response) { const error = new Error('An error occurred while fetching the data.') error.statusText = err.response.statusText; error.data = err.response.data?.user; throw error } // 处理无response的网络错误场景 const error = new Error('Network error') error.statusText = 'Network Error' throw error } } export const fetcher = (url) => getUser(url) export function useShouldMakeCallToApiUser(shouldMakeCall = false) { const { data: user, error, mutate } = useSWR(shouldMakeCall ? '/api/user' : null, fetcher, { revalidateOnFocus: false, revalidateIfStale: false, }) return { user: user?.data?.user, isLoading: !error && !user, mutate, isError: error?.statusText } }
优化后的代码和你原有使用逻辑完全兼容,AuthCheck组件不需要做任何修改。
内容的提问来源于stack exchange,提问作者Antonio Pavicevac-Ortiz
相关产品推荐
相关产品推荐

