十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

在 Preact Query 中接入 GraphQL:类型安全查询、代码生成与实战落地

在 Preact Query 中接入 GraphQL:类型安全查询、代码生成与实战落地 在 Preact Query 中接入 GraphQL类型安全查询、代码生成与实战落地【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query本文面向使用 TanStack Query 构建 Preact 应用的开发者讲解如何将 GraphQL 数据层无缝接入tanstack/preact-query。核心要点是Preact Query 的抓取机制以 Promise 为抽象基石因此可以与graphql-request、Apollo Client 等任意异步数据请求库协同工作在此基础上再结合 GraphQL Code Generator 实现全链路类型安全的查询与代码生成。读完本文你将掌握 GraphQL Preact Query 的完整接入模式并能在当前仓库中找到可直接运行的参考示例与底层源码依据。为什么 Preact Query 能与 GraphQL 顺畅协作在 TanStack Query 的框架文档中Preact 版 GraphQL 指南与 React 版共享同一份内容源——docs/framework/preact/graphql.md 的 front-matter 中声明了ref: docs/framework/react/graphql.md并通过replace规则将react-query替换为preact-query、React替换为Preact。这也从文档工程层面印证了一个核心事实数据抓取机制对数据源完全无感。原文明确指出Because React Querys fetching mechanisms are agnostically built on Promises, you can use React Query with literally any asynchronous data fetching client, including GraphQL!换成 Preact Query 语境同样成立只要你的queryFn返回一个 PromisePreact Query 就能接管其状态管理与缓存。GraphQL 客户端graphql-request、Apollo、urql 等本质上都是把 GraphQL 请求变成 Promise的库因此天然适配。从仓库源码可以进一步印证这一设计packages/preact-query/src/index.ts 导出了useQuery、useQueries等 hook同时第 4 行export * from tanstack/query-core表明所有框架适配层都建立在query-core之上queryFn的返回类型与执行都围绕 Promise 展开框架本身不关心请求协议是 REST、GraphQL 还是 gRPC。因此Preact Query 是否支持 GraphQL不是一个需要插件或适配器的问题——它是架构上天生支持的。你需要的只是一个 QueryClient 实例并挂载QueryClientProvider一个返回 Promise 的queryFn内部调用任意 GraphQL 客户端一个稳定的queryKey。必须知道的边界没有规范化缓存normalized cache原文在开篇用一个醒目提示强调了一个重要的边界Keep in mind that React Query does not support normalized caching. While a vast majority of users do not actually need a normalized cache or even benefit from it as much as they believe they do, there may be very rare circumstances that may warrant it so be sure to check with us first to make sure its truly something you need!翻译并展开说明TanStack Query含 Preact Query不做规范化缓存。缓存的最小单位是查询键queryKey 查询函数返回的数据数据以queryKey为索引整体存放而不会像 Apollo/Relay 那样把实体按类型与 ID 拆散、再自动组合。对绝大多数应用而言这并非缺陷基于 queryKey 的结构共享 精确失效模式更简单、更可预测配合queryClient.setQueryData/ 失效机制 已能覆盖绝大多数场景。但如果你确实需要依赖同一实体多处自动同步更新的能力即多个查询自动共享同一份实体数据且任一修改全局生效那么规范化缓存才值得考虑。原文的建议是先确认自己是否真的需要不要默认引入。从实现层面看query-core 中的数据存储围绕Query由queryKey标识展开缓存中不存在跨查询的实体索引结构这正是不提供规范化缓存的底层原因。准备工作安装依赖要让 Preact Query GraphQL 跑起来需要安装npm install tanstack/preact-query npm install graphql graphql-request版本与依赖约束说明packages/preact-query/package.json 显示当前仓库中该包版本为5.102.8其peerDependencies为preact: ^10.0.0也就是说要求 Preact 10 及以上graphql-request主流的 v5 版本支持 TS 泛型推断适合与类型安全代码生成配合graphql是 GraphQL 解析与类型系统基础库graphql-request依赖它来解析查询文档。仓库中对应的运行示例依赖examples/react/basic-graphql-request/package.json使用了graphql-request^7.1.2、graphql^16.9.0与tanstack/react-query^5.102.8。Preact 场景下仅需将 query 包替换为tanstack/preact-query。类型安全与代码生成graphql-request v5 GraphQL Code Generator原文给出的进阶玩法是Preact Query graphql-requestv5 及以上 GraphQL Code Generator以获得对 GraphQL operation 的完整类型检查——不仅查询结果的data是强类型的查询变量variables同样会被类型检查。思路分两步用 GraphQL Code Generator 根据 schema 生成类型化的graphql()辅助函数通常输出到gql/gql.ts在queryFn中把graphql(...)生成的类型化查询文档交给graphql-request执行。以查询星球大战系列电影列表为例原文的示例落到 Preact Query 语境如下import { request } from graphql-request import { useQuery } from tanstack/preact-query import { graphql } from ./gql/gql const allFilmsWithVariablesQueryDocument graphql(/* GraphQL */ query allFilmsWithVariablesQuery($first: Int!) { allFilms(first: $first) { edges { node { id title } } } } ) function Films() { // data 是完全类型化的 const { data } useQuery({ queryKey: [films], queryFn: async () request( https://swapi-graphql.netlify.app/.netlify/functions/index, allFilmsWithVariablesQueryDocument, // variables 同样会被类型检查 { first: 10 }, ), }) // ... }代码要点拆解./gql/gql是 Code Generator 生成的类型模块graphql()函数会把字符串模板解析为类型安全的 GraphQL 文档对象request(endpoint, document, variables)三个参数全部参与类型推导查询文档决定了 variables 与返回值的 TS 类型useQuery的queryFn只需返回 Promise——request的结果天然满足这一约束queryKey: [films]是缓存的唯一标识跨组件复用该 key 即可共享缓存。类型参数推导链结合 docs/framework/preact/reference/functions/useQuery.md 中记录的函数签名function useQueryTQueryFnData, TError, TData, TQueryKey(options, queryClient?): DefinedUseQueryResultTData, TErrorqueryFn返回什么类型TQueryFnData就会被推断为什么类型进而data字段自动获得相同类型。所以只要 GraphQL 客户端返回强类型 PromiseuseQuery的data就是强类型的——类型系统由请求库一路贯通到组件渲染层。把 GraphQL Preact Query 的最小应用完整跑起来为了让上文代码真正可运行还需要补上 QueryClient 的引导bootstrap部分。一个最小可运行的 Preact 应用骨架如下import { render } from preact import { QueryClient, QueryClientProvider, useQuery, } from tanstack/preact-query import { request } from graphql-request const endpoint https://graphqlzero.almansi.me/api const queryClient new QueryClient() function App() { return ( QueryClientProvider client{queryClient} Posts / /QueryClientProvider ) } function Posts() { const { status, data, error, isFetching } useQuery({ queryKey: [posts], queryFn: async () { const { posts } await request{ posts: Array{ id: number; title: string } }( endpoint, /* GraphQL */ query { posts { id title } } , ) return posts }, }) if (status pending) return pLoading.../p if (status error) return pError: {error.message}/p return ( div ul {data.map((post) ( li key{post.id}{post.title}/li ))} /ul {isFetching ? pBackground Updating.../p : null} /div ) } render(App /, document.getElementById(root)!)其中QueryClientProvider负责向组件树提供 queryClient 上下文所有useQuery调用都会从最近的 Provider 取用实例没有显式泛型时data的类型由requestT的泛型决定也可在useQuery上显式声明四个类型参数status/isFetching等返回值与 React Query 完全一致渲染分支模式通用。仓库内的可运行参考示例当前仓库虽然没有独立的 Preact GraphQL 示例目录但在 examples/react/basic-graphql-request/src/index.tsx 中提供了一个结构完整、可直接对照学习的示例源码中已配置 Vitenpm install npm run dev即可运行。该示例演示了几个值得借鉴的工程模式列表/详情两套查询共用缓存用usePosts()key 为[posts]与usePost(postId)key 为[post, postId]区分两个查询用缓存判断数据是否已存在列表页通过queryClient.getQueryData([post, post.id])判断详情是否已被缓存据此把已访问过的文章标题加粗显示——这是非规范化缓存模型下预取感知的典型用法后台刷新提示isFetching为 true 时显示 Background Updating...让用户感知重新访问时发生的数据刷新条件启用详情查询使用enabled: !!postId示例源码postId 无效时不发起请求。该示例同样使用graphql-requestgqlrequest具名导入访问 GraphQLZero 的公开 GraphQL APIhttps://graphqlzero.almansi.me/api。把其中的tanstack/react-query导入替换为tanstack/preact-query、组件写法改为 Preact 即可迁移到 Preact 场景——这与本文开头提到的文档replace映射逻辑完全一致。进阶封装自定义 GraphQL hooks沉淀可复用数据层实践中通常会把端点 文档 queryKey封装为自定义 hook避免在组件里散落 GraphQL 细节。例如对文章详情场景function usePost(postId: number) { return useQuery({ queryKey: [post, postId], queryFn: async () { const { post } await request{ post: Post }( endpoint, /* GraphQL */ query { post(id: ${postId}) { id title body } } , ) return post }, enabled: !!postId, }) }这套写法的收益所有 GraphQL 请求细节文档字符串、端点、类型都被封装在 hook 内组件只消费data/status/error配合 Code Generator 时hook 的入参postId与返回值都自动获得精确类型结合queryOptions可以把同一组选项在useQuery与queryClient.prefetchQuery等命令式 API 之间复用详情可参考 query-options 指南。与取消、重试等能力的协同GraphQL 请求同样享受 Preact Query 的完整生命周期能力查询重试、超时由query-core统一管理若使用支持 AbortSignal 的 GraphQL 客户端还可配合 query-cancellation 指南 实现请求取消失效与后台刷新逻辑对 GraphQL 与 REST 一视同仁可参阅 query-functions 指南 了解queryFn的上下文参数如signal、queryKey、meta。小结把本文要点收敛为一张接入决策清单架构前提Preact Query 基于 Promise 抽象GraphQL 客户端天然可用无需任何适配层边界认知无规范化缓存多查询共享实体需通过统一的 queryKey 失效/写入策略管理类型安全路线graphql-requestv5 提供泛型推断叠加 GraphQL Code Generator 生成的graphql()可让查询文档、variables、返回数据三者类型闭环运行骨架QueryClientQueryClientProvider 返回 Promise 的queryFn 稳定queryKey即可让 GraphQL 应用获得缓存、后台刷新、重试、失效等开箱能力仓库参照React 版 GraphQL 示例 展示了含缓存感知 UI、后台刷新提示的完整列表/详情模式迁移到 Preact 仅需替换包名。以 Promise 为桥Preact Query 与 GraphQL 的结合是配置即所得的简单加法——把精力留给真正需要决策的缓存策略与类型设计即可。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表