V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
爱意满满的作品展示区。
iliaoliao

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

  •  2
     
  •   iliaoliao ·
    liaoliao666 · Sep 20, 2023 · 3408 views
    This topic created in 952 days ago, the information mentioned may be changed or developed.

    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 replies    2023-09-25 09:52:56 +08:00
    codehz
        1
    codehz  
       Sep 20, 2023
    怎么感觉这设计和某些 graphql 库很像🤔️
    iliaoliao
        2
    iliaoliao  
    OP
       Sep 20, 2023
    @codehz Apollo Client 和 GrahQL 也有参考一些。
    heyleo
        3
    heyleo  
       Sep 20, 2023
    没想到能在 v 站上面碰到同事。。赞一波,已 star
    iliaoliao
        4
    iliaoliao  
    OP
       Sep 20, 2023
    @heyleo 好兄弟
    shunia
        5
    shunia  
       Sep 21, 2023
    正常一个 fetcher 应该是这样:
    (title, id, content, authHeader | undifined) => <ResponseValueType>

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

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

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

    至于 fetcher 是因为与请求库无关的,而其他 GraphQL 库的请求完全是由它们自身处理,自然它们能涵盖请求体的这些信息。
    qingyaun
        7
    qingyaun  
       Sep 22, 2023   ❤️ 1
    作者的 react-query-kit 也很不错👍
    pannanxu
        8
    pannanxu  
       Sep 25, 2023
    我的想法:集成 quaere-axios 、quaere-fetch 。然后使用的时候就可以直接采用
    ```js
    const anQuery = query(url);
    ```
    解放我的双手
    iliaoliao
        9
    iliaoliao  
    OP
       Sep 25, 2023
    @pannanxu 简单写个高阶函数就可以了,没啥必要单独写个库
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5879 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 02:48 · PVG 10:48 · LAX 19:48 · JFK 22:48
    ♥ Do have faith in what you're doing.