useFetch Pattern useFetch 自定义 Hook

最后更新:2026-10-28

useFetch Pattern useFetch 自定义 Hook

把三态请求逻辑抽成 useFetch(url) 自定义 Hook:组件一行调用拿到 { data, loading, error },请求状态不再散落各处。这是「逻辑复用」的经典案例,也是理解 TanStack Query 的台阶。

分组数据与工程化
类型模式

ℹ️ 说明 编辑器将 JSX 转译为 JavaScript 后在沙箱中渲染真实界面;组件自动挂载,无需手写 render 调用。

📝 语法

function useFetch(url) {
  const [state, setState] = useState({ data: null, loading: true, error: null })
  useEffect(() => {
    const ctrl = new AbortController()      // 换 url / 卸载时取消旧请求
    setState({ data: null, loading: true, error: null })
    fetch(url, { signal: ctrl.signal })
      .then(r => r.ok ? r.json() : Promise.reject(new Error('HTTP ' + r.status)))
      .then(data => setState({ data, loading: false, error: null }))
      .catch(err => err.name !== 'AbortError' &&
        setState({ data: null, loading: false, error: err }))
    return () => ctrl.abort()               // cleanup:防止过期响应覆盖新数据
  }, [url])
  return state
}

⚙️ 参数

url请求地址;作为依赖,url 变化时 Hook 自动重新请求并取消上一次。

返回值:无返回值,作为编码模式使用

▶ 示例

示例可直接运行:展开后自动渲染,编辑代码即时生效。

输出结果:

点「切到 #2」自动重新请求并短暂显示加载态,随后渲染对应 todo——组件只写一行 useFetch(url),三态逻辑全部复用。

💡 要点

💡 提示 进阶版加 refetch 手动刷新函数与模块级 cache Map,就逼近 TanStack Query 的雏形(见下节)。
⚠️ 注意 并发切换时旧请求可能后返回并覆盖新数据:必须 abort 或像示例那样用 alive 标记丢弃过期响应。
ℹ️ 说明 自定义 Hook 名字必须以 use 开头,内部才能合法调用其他 Hook,lint 规则也据此检查。
更多案例整理中,敬请期待。

📚 相关教程

❓ 常见问题

Q 组件卸载后 setState 会警告吗?
A React 18 起不再警告,但写入是浪费且可能错序;保留 abort/alive 清理仍是好习惯。
Q 怎么支持 POST?
A 把方法与请求体作为参数传入 useFetch(url, options),或为写操作单独封装一个 mutation 型 Hook。
Q 两个组件用同一 url 会请求两次吗?
A 会。Hook 状态是调用级别的,不共享;需要共享缓存请用 TanStack Query 或自建模块级缓存。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏