前端缓存【免费下载链接】swrReact Hooks for Data Fetching项目地址https://gitcode.com/gh_mirrors/sw/swr点击查看免费下载导读本指南基于 SWR 官方仓库中的 basic-typescript 示例讲解如何用 TypeScript 为 SWR 的数据请求链路引入完整的类型约束从带泛型的 fetcher 函数到useSWR声明式地标注响应数据类型再到 Next.js 动态路由页面的数据结构声明。读完本文你将掌握在 Next.js SWR TypeScript 项目里搭建一条从接口返回到 UI 渲染全程类型安全的请求链路的完整做法并理解 SWR 内部泛型推断的底层原理。一、示例定位官方 TypeScript 入门模板仓库根目录下的 examples/basic-typescript/README.md 明确给出了该示例的核心目标Show how to use the basic example along with TypeScript to type the data received from SWR.即在 SWR 基础用法之上叠加 TypeScript为 SWR 获取到的数据提供类型标注。它与纯 JavaScript 版本的 examples/basic 示例形成对照——后者只演示在两个页面从 API 获取数据的基本用法而本示例的全部价值就在于给这条请求链路加上类型。整个示例是一个最小可运行的 Next.js 应用由四个文件组成文件职责libs/fetch.ts带泛型的类型安全 fetcherpages/index.tsx首页请求项目列表string[]pages/[user]/[repo].tsx动态路由页请求 GitHub 仓库统计数据对象结构pages/api/data.tsNext.js API 路由模拟慢速接口下面从运行方式、fetcher 设计、页面数据消费三个层面逐一展开。二、快速运行下载、安装与启动2.1 下载示例官方 README 提供了一条基于 curl tar 的下载命令直接从 SWR 仓库的主分支中剥离出该示例目录curl https://codeload.github.com/vercel/swr/tar.gz/main | tar -xz --strip2 swr-main/examples/basic-typescript cd basic-typescript命令说明--strip2会去掉压缩包内swr-main/examples/basic-typescript/的前两级目录将示例内容直接解压到当前目录。2.2 安装与启动README 同时给出了 yarn 与 npm 两种等价方式yarn yarn dev # 或 npm install npm run dev对应到 examples/basic-typescript/package.json 中的 scripts 配置scripts: { dev: next, start: next start, build: next build }三个脚本分别对应开发模式next、生产运行next start需先执行 build与生产构建next build。2.3 依赖组成依赖清单展示了该示例的技术栈组合dependencies: { next: latest, react: latest, react-dom: latest, swr: latest }, devDependencies: { types/node: 16.7.2, types/react: 17.0.19, typescript: 4.3.5 }要点运行时依赖全部取最新版其中swr直接依赖当前仓库的发布版本TypeScript 相关类型包放在 devDependenciestypes/node、types/react、typescript类型标注只影响编译期不参与运行时打包注意这里没有独立的types/swr因为 SWR 自带的类型定义已足够完整这也是官方示例不需要额外类型包这一事实的最好证明。2.4 TypeScript 编译配置examples/basic-typescript/tsconfig.json 是一份标准的 Next.js TypeScript 配置其中与类型安全直接相关的关键项compilerOptions: { target: es5, lib: [dom, dom.iterable, esnext], allowJs: true, strict: true, forceConsistentCasingInFileNames: true, noEmit: true, esModuleInterop: true, module: esnext, moduleResolution: node, resolveJsonModule: true, isolatedModules: true, jsx: preserve }值得注意的两点strict: true开启全部严格模式选项确保 fetcher 与页面中的类型标注真正生效、不留类型盲区noEmit: true表明该配置仅供类型检查实际编译产物由 Next.js 的打包链路负责与next-env.d.ts配合即可满足开发时类型检查需求next-env.d.ts 由 Next.js 自动维护官方注明不应手动编辑。三、核心一带泛型的类型安全 fetcher3.1 示例中的 fetcher 实现libs/fetch.ts 是整个示例类型安全的起点export default async function fetcherJSON any( input: RequestInfo, init?: RequestInit ): PromiseJSON { const res await fetch(input, init) return res.json() }逐行拆解JSON any泛型默认值fetcher 声明了一个名为JSON的泛型名字取自JSON 响应体的语义与内置JSON对象并无冲突默认值为any。这意味着调用方若不指定类型行为退化为普通 JavaScript一旦调用方通过泛型或上下文推断给出类型整个返回值的Promise包装层就拥有了精确类型参数类型input: RequestInfo与init?: RequestInit直接复用 DOM 标准类型即fetch()原生签名因此这个 fetcher 能无缝兼容任意 URL 字符串或Request对象返回值PromiseJSON即响应体反序列化结果被类型化为调用方声明的数据类型。这段实现与其 JavaScript 版对照物 examples/basic/libs/fetch.js 在运行时行为上完全一致都是fetch → res.json()差异全部集中在类型层——这正是同样的逻辑多一份类型保障的直观体现。3.2 泛型是如何向下流动的Fetcher 类型定义从源码层面看SWR 内部用条件类型为 fetcher 建立了由 Key 推导参数类型的约束。在 src/_internal/types.ts 中export type Fetcher Data unknown, SWRKey extends Key Key SWRKey extends () (infer Arg) | null | undefined | false ? (arg: Arg) FetcherResponseData : SWRKey extends null | undefined | false ? never : SWRKey extends infer Arg ? (arg: Arg) FetcherResponseData : never这套条件类型表达了三条规则Key 是函数若 Key 是返回值的函数如() /api/datafetcher 的参数类型就是该函数的返回值类型ArgKey 是空值若 Key 是null | undefined | falsefetcher 类型为never——因为此时 SWR 根本不会发起请求对应useSWR(null, fetch)的禁用请求场景Key 是普通值否则 fetcher 的参数类型就是 Key 本身。FetcherResponseData定义于 src/_internal/types.ts即Data | PromiseData允许 fetcher 返回数据本身或一个 Promise。因此示例中fetcher的PromiseJSON返回类型天然满足 SWR 的FetcherResponse约束。3.3 从useSWR泛型到响应类型SWR 的公开入口 src/index/index.ts 将 src/index/use-swr.ts 中的useSWRHandler以useSWRData any, Error any的签名导出。Data与Error两个泛型会一路传递到 hook 的返回值SWRResponseData, Error中最终让data、error、mutate等都拥有对应类型。这意味着使用方只需要在调用useSWR时声明Data泛型通常配合fetcher的返回类型就能让编译器在data.xxx访问处做完整的属性存在性校验——这正是下一节页面代码演示的用法。四、核心二页面中的类型化数据消费4.1 首页请求string[]列表pages/index.tsx 展示了最简单的类型标注import Link from next/link import fetch from ../libs/fetch import useSWR from swr export default function HomePage() { const { data } useSWRstring[](/api/data, fetch) const { data: data2 } useSWR(null, fetch) return ( div style{{ textAlign: center }} h1Trending Projects/h1 {data2} div {data ? data.map(project ( p key{project} Link href/[user]/[repo] as{/${project}} {project} /Link /p )) : loading...} /div /div ) }两个值得深入解读的细节细节一useSWRstring[]显式泛型useSWRstring[](/api/data, fetch)告诉 SWR/api/data返回的是字符串数组。于是data.map(project ...)中project被推断为stringkey{project}与 Link 的as{/${project}}都获得类型校验渲染分支data ? ... : loading...中data被收窄为非空数组这正是 SWR 的data在无缓存时可能为undefined的运行时事实在类型层的反映。细节二useSWR(null, fetch)的条件请求写法第二行useSWR(null, fetch)把 Key 显式设为null这是 SWR 官方的禁用请求惯用法。回到 src/_internal/types.ts 的Fetcher条件类型null会让 fetcher 类型变为never类型系统因此知道这个 hook 永远不会发起网络请求。同时data2类型为string | undefined本示例中未赋值实际渲染为空。这种写法常用于等待用户输入/条件满足后再请求的场景。4.2 动态路由页请求结构化对象pages/[user]/[repo].tsx 演示了对复杂对象结构的类型化import Link from next/link import fetch from ../../libs/fetch import useSWR from swr export default function Repo() { const id typeof window ! undefined ? window.location.pathname.slice(1) : const { data } useSWR{ forks_count: number stargazers_count: number watchers: number }(/api/data?id id, fetch) return ( div style{{ textAlign: center }} h1{id}/h1 {data ? ( div pforks: {data.forks_count}/p pstars: {data.stargazers_count}/p pwatchers: {data.watchers}/p /div ) : ( loading... )} br / br / Link href/Back/Link /div ) }解读内联对象类型泛型参数直接写为对象字面量类型{ forks_count: number; stargazers_count: number; watchers: number }无需额外定义 interface。访问data.forks_count等字段时编译器会校验属性是否存在且类型为number模板字符串 Key/api/data?id id使 Key 携带查询参数SWR 会为每个不同的id建立独立缓存条目配合下方 API 路由可看到按仓库分别缓存的效果SSR 安全处理typeof window ! undefined判断避免在服务端渲染时访问window此时id为空字符串请求路径为/api/data?id。4.3 背后的运行时行为从 useSWRHandler 看数据流类型标注的运行时载体是 src/index/use-swr.ts 中useSWRHandler的核心流程_key首先经过serialize得到序列化后的key与传给 fetcher 的fnArg然后基于 cache 订阅状态按revalidateOnMount、revalidateIfStale等配置决定是否立即发起请求src/index/use-swr.ts。实际发起请求时fetcher 被以currentFetcher(fnArg)的方式调用其结果与时间戳一起存入全局FETCH表用于请求去重src/index/use-swr.ts。同一个页面中多个组件对同一 Key 调用useSWR时只会触发一次网络请求——这是类型安全之外SWR 带来的另一个核心收益自动去重与缓存共享。五、配套 API 路由模拟慢速接口pages/api/data.ts 是 Next.js API 路由负责提供两个接口import { NextApiRequest, NextApiResponse } from next const projects [ facebook/flipper, vuejs/vuepress, rust-lang/rust, vercel/next.js ] export default function api(req: NextApiRequest, res: NextApiResponse) { if (req.query.id) { // a slow endpoint for getting repo data fetch(https://api.github.com/repos/${req.query.id}) .then(resp resp.json()) .then(data { setTimeout(() { res.json(data) }, 2000) }) return } setTimeout(() { res.json(projects) }, 2000) }设计意图非常清晰无id参数返回写死的项目名数组projects对应首页useSWRstring[]的数据源带id参数作为服务端代理转发请求到 GitHub 的https://api.github.com/repos/${req.query.id}把响应原样回传给浏览器对应动态路由页的对象数据源两处setTimeout(..., 2000)刻意制造 2 秒延迟模拟真实网络环境。这正好用来观察 SWR 的加载态表现——页面代码中的loading...分支在请求完成前会一直渲染2 秒后数据到达并触发 UI 更新。提示该 API 路由直接依赖外部的 GitHub API。在无网络环境中服务端代理请求会失败此时可自行将/api/data的响应替换为本地 mock 数据不影响前端类型化演示的效果。六、从 basic 到 basic-typescript类型化前后的差异将 examples/basic/libs/fetch.js 与 examples/basic-typescript/libs/fetch.ts 对照可以看到类型化带来的三处差异维度纯 JS 版TS 版fetcher 参数隐式...args任意类型input: RequestInfo、init?: RequestInitDOM 标准类型返回值无约束PromiseJSON泛型可推导useSWR 调用useSWR(/api/data, fetch)data为隐式anyuseSWRstring[](...)data.map中的元素为string这正是 SWR 官方刻意维持的一对镜像示例运行时行为零差异开发期体验天壤之别——TS 版让所有数据访问点都处于编译器监督之下接口结构调整时会立刻在 IDE 中暴露类型错误而不是等到运行时才出错。七、延伸实践把类型安全用到更大的工程里在掌握示例之后可以按以下路线将其推广到真实项目抽取接口类型将内联对象类型如{ forks_count: number }提取为interface或type配合fetcherJSON的泛型做到接口返回结构一处定义、多处复用复用同一 fetcherlibs/fetch.ts的 fetcher 不绑定任何具体 API可在全项目共享换用 axios 时只需保持同样的泛型签名fetchDataT(...args): PromiseT页面代码无需改动合理利用条件请求useSWR(null, fetch)写法适合依赖登录态、表单输入等条件才请求的场景配合Fetcher条件类型可在类型层面阻止对空 Key 的误调用关注 strict 配置保持tsconfig.json的strict: true让泛型标注真正生效若项目中存在历史 JS 文件allowJs: true允许渐进式迁移。八、小结本示例虽然规模极小却完整覆盖了TypeScript × SWR × Next.js三者结合的最小闭环fetcher 层用泛型PromiseJSON封装fetch().json()作为类型入口调用层useSWRData显式声明响应类型使数据消费点全部类型安全源码支撑SWR 的Fetcher条件类型src/_internal/types.ts与useSWRHandler泛型签名src/index/use-swr.ts共同保证了Key 决定 fetcher 参数、fetcher 返回类型决定 data 类型的完整推导链路运行验证yarn dev启动后访问首页与任一[user]/[repo]路由即可在 2 秒延迟的接口下观察加载态与类型化数据渲染的完整效果。这条类型安全的数据获取链路就是 SWR 官方为 TypeScript 用户准备的入门台阶也是将 SWR 引入大型工程时最值得先落地的一层基础设施。赞分享前端缓存【免费下载链接】swrReact Hooks for Data Fetching项目地址https://gitcode.com/gh_mirrors/sw/swr点击查看免费下载相关推荐Tamagui与TypeScript泛型构建类型安全的可复用组件Tamagui与TypeScript泛型构建类型安全的可复用组件 在React应用开发中组件复用与类型安全往往难以兼得。Tamagui作为支持React NUI组件设计系统前端跨平台browserify与TypeScript泛型复杂数据结构的类型安全处理browserify与TypeScript泛型复杂数据结构的类型安全处理 在前端开发中随着应用复杂度提升处理嵌套数组、异构对象等复杂数据结构时JavaS前端构建CLI开发工具Saucer现代C跨平台Webview库终极指南 — 轻量级构建桌面应用新方案Saucer现代C跨平台Webview库终极指南 — 轻量级构建桌面应用新方案 Saucer是一款现代C跨平台Webview库能够帮助开发者轻松构建上一篇coinbasepro-python完整指南10分钟掌握Coinbase Pro API交易下一篇Cat-Catch 2.5.9版本发布浏览器资源嗅探的智能升级与专业级下载体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考