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 或自建模块级缓存。