You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React自定义SWR条件请求钩子写法是否正确?能否避免不必要接口调用?

结论

你的封装基本可以解决重复请求的问题,但存在冗余代码和潜在的错误点,可以进一步优化。


为什么现有封装能解决重复请求问题

  • 你正确使用了SWR的条件请求特性:当传入useSWR的第一个参数为null时,SWR会直接跳过请求逻辑,不会发起接口调用。
  • 你主动关闭了revalidateOnFocus、revalidateIfStale两个默认会触发自动重新验证的配置项,避免了窗口聚焦、数据过期等场景下的非预期额外请求。
  • 只有当你调用useShouldMakeCallToApiUser传入参数为true时,才会把/api/user地址传给SWR触发请求,确实只会在引入钩子的组件加载时触发一次请求,不会出现无意义的重复调用。

现有代码的可优化点

  1. 存在冗余的状态和嵌套钩子定义:你当前代码里的useState、useEffect以及嵌套的useUser函数都是没有必要的,直接扁平化处理即可,不会影响原有功能,还能避免额外的重渲染开销。
  2. fetcher的catch分支存在报错风险:当请求出错且没有err.response(比如跨域、网络中断)时,你写的return await res.json()中的res是未定义的,会触发二次错误。
  3. 原代码中给非异步的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 22:06:04