[开源自荐] Quaere - 货拉拉内部的原子化服务端状态管理库. - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
iliaoliao
V2EX    分享创造

[开源自荐] Quaere - 货拉拉内部的原子化服务端状态管理库.

  •  2
     
  •   iliaoliao
    liaoliao666 2023-09-20 10:12:58 +08:00 3137 次点击
    这是一个创建于 764 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Quaere 是什么

    "Quaere" 是一个 React 的原子化服务端状态管理库。

    Quaere 的核心实现来自于 Tanstack Query,但去除了 queryKey 概念,API 设计类似于 Jotai,提供了一套声明式的、原子化的状态管理方案,帮助你高效地管理服务端状态。

    动机

    Tanstack QuerySWR 在服务端状态管理上已经做得很不错,但仍然有下面的一些痛点。

    • 需要手动地管理你的 queryKey 和异步资源的对应关系。
    • 没有统一的地方管理,其 hook 很容易散落在项目各处。
    • 涉及到异步资源的操作时对 typescript 类型不友好。

    Quaere

    如果我既想受益于主流库,又没有这些痛点,怎么办呢?

    Quaere 就是为了解决这个问题而诞生的,它既包含了主流库特性也提供了一套声明式的、原子化的状态管理方案。

    快速开始

    下面是一个最基本的示例:

    import { query } from "quaere"; const anQuery = query({ fether: (variables) => axios.get(url, variables), }); 
    import { useQuery } from "quaere"; function Example() { const { data } = useQuery({ query: anQuery, variables }); } 

    上面的示例展示了 Quaere 的两个核心函数:

    • query:用于创建一个异步资源解析配置,我们称其为 "查询配置"。

    • useQuery:该 hook 用于读取 "查询配置" 发起请求,并且每个不同 variables 都会返回与其相应的服务端状态。

    Typescript

    默认情况下,Quaere 会从 fetcher 推断出 类型,因此你可以自动获得首选类型。

    const todoQuery = query({ fetcher: (variables: { id: number }) => { return { title: "todo" }; }, }); // variables 将被推断为 { id: number }, data 将被推断为 { title: string } const { data } = useQuery({ query: todoQuery, variables: { id: 1 } }); 

    你还可以显式地指定 variablesdata 参数的类型。

    type Data = { title: string }; type Variables = { id: number }; const todoQuery = query<Data, Variables>({ fetcher: (variables) => { return { title: "todo" }; }, }); 

    RealWorld Examples

    V2Fun 在网络体验方面完全受益于 Quaere 的各种特性,你可以从 V2Fun 源码中看到各种 Quaere 的真实世界使用案例。

    查看完整的文档和示例,请访问 quaere-site.vercel.app. 查看源码,请访问 quaere.

    9 条回复    2023-09-25 09:52:56 +08:00
    codehz
        1
    codehz  
       2023-09-20 10:19:26 +08:00
    怎么感觉这设计和某些 graphql 库很像
    iliaoliao
        2
    iliaoliao  
    OP
       2023-09-20 10:24:51 +08:00
    @codehz Apollo Client 和 GrahQL 也有参考一些。
    heyleo
        3
    heyleo  
       2023-09-20 11:53:43 +08:00
    没想到能在 v 站上面碰到同事。。赞一波,已 star
    iliaoliao
        4
    iliaoliao  
    OP
       2023-09-20 14:00:16 +08:00
    @heyleo 好兄弟
    shunia
        5
    shunia  
       2023-09-21 10:42:16 +08:00
    正常一个 fetcher 应该是这样:
    (title, id, content, authHeader | undifined) => <ResponseValueType>

    然后使用的时候正常应该像这样:
    use(query, [...requestParameters] | undefined, options | undifined)

    object 形式的入参的涵义就是可选的,虽然我知道 ts 可以很好的表达 object 中的可选值和必须值,但是还是觉得有点奇怪。
    我觉得可以参考 nodejs 的 api ,重新考虑一下方法入参的设计。

    省略两个常用库里的“key”的概念确实是比较大的卖点,支持一下。
    iliaoliao
        6
    iliaoliao  
    OP
       2023-09-21 11:29:21 +08:00
    @shunia 很专业,入参的设计考虑过像你建议的形式。但因为支持第一个参数为 query 的话会增加不少 typescript 代码,而且会与其他 API 产生割裂感,如 setQueryData 和 getQueryData 入参都是 { query, variables } 一般的 object 形式。但不排除以后会支持。

    至于 fetcher 是因为与请求库无关的,而其他 GraphQL 库的请求完全是由它们自身处理,自然它们能涵盖请求体的这些信息。
    qingyaun
        7
    qingyaun  
       2023-09-22 15:08:51 +08:00   1
    作者的 react-query-kit 也很不错
    pannanxu
        8
    pannanxu  
       2023-09-25 09:48:26 +08:00
    我的想法:集成 quaere-axios 、quaere-fetch 。然后使用的时候就可以直接采用
    ```js
    const anQuery = query(url);
    ```
    解放我的双手
    iliaoliao
        9
    iliaoliao  
    OP
       2023-09-25 09:52:56 +08:00
    @pannanxu 简单写个高阶函数就可以了,没啥必要单独写个库
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3202 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 11:08 PVG 19:08 LAX 04:08 JFK 07:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86