@forge-go/client-react

中文文档
1.13.7发布于 2026/11/12MITTypeScriptES Module零依赖近 30 天下载 2600

对 Forge 客户端运行时间的回放绑定: 使用SyncExternalStore 来覆盖已规范的查询缓存

中文使用文档
文档目录7 节
  1. 配置客户端
  2. 它的保证
  3. 刷新您不持有的查询
  4. 实时查询
  5. 服务器渲染
  6. 还没做什么
  7. 同伴依赖关系

@ forge-go/ 客户端反应

反应绑定 @forge-go/client-core三根钩子和一个 提供商, 1.07 kB gzipped.

一切决定 什麽 价值是——身份、僵硬、分化, 无效性——是在核心中决定的,在没有渲染器的情况下可以测试. 剩下的是满足的狭隘工作 useSyncExternalStore是因为 合同没有取消任何合同.

import { useQuery, useMutation } from '@forge-go/client-react';
import { useOrderList, useOrderCreate } from './generated/hooks';

function Orders() {
  const { data, status, error, isFetching, refetch } = useQuery(useOrderList, {
    query: { status: 'open' },
  });
  const create = useMutation(useOrderCreate);

  if (status === 'pending') return <Spinner />;

  return (
    <>
      <button disabled={create.isPending} onClick={() => create.mutate({ body: { total: 0 } })}>
        New order
      </button>
      {create.status === 'error' && <Warning error={create.error} />}
      <ul>{data?.map((order) => <Row key={order.id} order={order} />)}</ul>
    </>
  );
}

mutate 从不拒绝: 失败 status 财务报告和审定财务报表 error,则 承诺解决 undefined这是故意的, 这就是为什么处理者 上面需要没有 .catch。记录错误的突变 财务报告和审定财务报表 拒绝 请每个召唤者记取一个--每个被遗忘的-- .catch 是一个 unhandledrejection 每写作失败, 生产中意味着提示射击 关于用户已经查看的错误.

当您在写完之后需要按顺序工作时,如果没有,则不得继续工作 要求拒绝姓名:

await create.mutateAsync({ body: { total: 0 } }); // throws on failure
router.push('/orders');

两者记录相同状态. 唯一的区别是谁是失败的主人.

第一个参数是生成物的绑定 hooks.ts (单位:千美元)export const useOrderList = query(ops.orderList)),这是一个模块级 常数。 没有每个端点的钩子可以生成 也没有再生 当此软件包改变时.

配置客户端

configureClient() 从核心本身就够了:

import { configureClient, RestTransport } from '@forge-go/client-core';
import { entities } from './generated/ops';
import { client } from './generated/rest';

configureClient({ transport: new RestTransport({ client }), entities });

ClientProvider 实值 选项并故意这样做。 生成 hooks.ts (a) 早在应用程序存在之前就将任何东西交给模块范围; 要求提供者将意味着从 Go 路由表重生的文件 决定消费性应用如何进行依赖性注射。 打开一个 一个全局是错误的答案——服务器同时处理两个请求,a 测试,不能漏入下一个, 应用程序对两个 后端 :

<ClientProvider client={cache}>
  <App />
</ClientProvider>

决议是明确的,然后提供,然后是全球性的: useQuery(op, args, {client}) 击败供应商,击败 configureClient三个都没有, getClient() 扔出一个名称而不是刻出一个抓取缓存,什么也没有 别人也看得出来.

它的保证

  • 每个查询一个请求,而不是每个组件. 两个部分呼叫 useQuery(useOrderList) 是一个缓存条目,一个注册挂载和一个 请求。 他们一起定居.
  • 写给 Order:7 只重写参考文献 Order:7。 。 。 . 没有 无效在组件中被写入; 服务器已声明 .
  • 一个不变的实体在反射处保留其对象身份,所以一个 memo'会排出它跳过。 集装箱没有保证:新鲜的 反应是一种新鲜的骨架,商店并不声称知道 列表的形状不变。 身份在身份已知的地方得到保障.
  • 严格模式的挂载 / 卸载 / 挂载 , 叶片完全是一个活订阅 并且不会引起第二次请求——关于套接字和查询.
  • live 每个呼叫站点都选择进入,并在下面共享. 两个组件在 相同的实时查询是 1 订阅; 2 不同 实时查询 使用同一通道的实体是一个连接.

刷新您不持有的查询

useQuery 手举起 refetch 用于打开该组件的查询。 当 写别的地方,使用 useInvalidate数字 :

import { useInvalidate, useMutation } from '@forge-go/client-react';
import { useOrderArchive, useOrderList } from './generated/hooks';

function ArchiveDialog({ id, onDone }: { id: number; onDone: () => void }) {
  const archive = useMutation(useOrderArchive);
  const invalidate = useInvalidate();

  return (
    <button
      onClick={async () => {
        await archive.mutateAsync({ path: { id } });
        invalidate(useOrderList);
        onDone();
      }}
    >
      Archive
    </button>
  );
}

你给行动起名,从不给部件起名. useOrderList 是模块级 生成的常数 hooks.ts,所以对话框导入它想要的读取 清新和保持无知 任何列表 碰巧显示它.

三种说法:

invalidate(useOrderList);                     // every cached variant
invalidate(useOrderGet, { path: { id: 7 } }); // that one exactly
invalidate.tags(['Order[]', 'Order:7']);      // the tag graph directly

不通过参数而覆盖每页,过滤并排序缓存所控 通常你的意思是,一旦一个字落地。 过 参数,你得到一个查询 他们按键,同一个键 useQuery 计算 当其他组件打开时。 一个皱纹. invalidate(op) 财务报告和审定财务报表 invalidate(op, {}) 不为同一查询命名, 因为一个读取了没有 参数与空对象调用的参数不同 不争辩的表 覆盖两者.

invalidate 标记查询暂停和返回。 挂载在下一条 组合成一回合 请求。 卸载者保留旗子,在下次登上时进行反射,所以 在路径中列出您在返回之前 避免了成本成本 对它.

须等时取名相求:

await archive.mutateAsync({ path: { id } });
await invalidate.refetch(useOrderList);
onDone();

火柴一解决就解决了 是一个对话框关闭之前想要的 . 它拒绝失败,像 mutateAsync 和与 mutate。未挂载匹配 保持懒惰。 查找二十个缓存过滤器组合 20项申请将毫无意义.

到达 tags 您的操作声明 provides这是 运行时间本身的模型, 它保留在服务器上的决定 其中的chema 活着 大部分生成的今天没有声明,所以可以调用的形式 按操作处理查询,并工作到标记图是否有边缘 来点新鲜的.

useInvalidate(cache) 使用相同的覆盖 useClient 夺去,并解决 同样的方式,没有了一个,所以你无效 通过你读到的缓存。 这个 只要缓存稳定,就可以放回去 或把它交给一个 memo'孩子'.

实时查询

const { data } = useQuery(useOrderList, { query: { status: 'open' } }, { live: true });

它订阅每个频道的列表 绑定到这个查询的实体 结果类型可以包含,并在最后一个消费者卸载时释放出. A 类 框架直接更新存储, 所以 order.updated 没有要求.

专访,每个呼叫网站,故意. 自动就更少了 字符和两个更糟糕的属性: 开发者读取组件不能 更长的时间显示它是否持有套接字, 以及应用程序的连接数 将成为造物树的产物.

live 是一个普通道具,所以它可能会改变。 正在尝试订阅或发行 并且确实 无 至查询——无再挂载、无回移、无装入状态. 打开它并不能掩盖它关闭的窗口:新鲜是 缓存的业务,和 live 不是一个隐藏的还原触发器。 差距 真正的是运行时间的过错,一个被丢弃的套接字被核心回收.

它需要一个流跑时间——a StreamBinder 建在同一缓存上. 没有一个人, {live: true} 通过缓存报告 onError 而不是说 静悄悄地递回一个从未更新的查询 .

服务器渲染

import { HydrationBoundary } from '@forge-go/client-react';

<HydrationBoundary state={state} ops={ops}>
  <OrderTable />
</HydrationBoundary>

state 这是什么 dehydrate 在服务器上生产 ops 是生成的 操作表直接通过. hydrate 需要它是因为缓存 记录有 OperationMeta 晚点再换一个.

它在制成过程中而不是在作用中水合物. 儿童阅读 getSnapshot 在它们自己做成的过程中, 发生在此组件之后 使返回,所以在第一次通过时,它们可以看到一个变相水合物. 在树下行走之后, 效果是: 第一个涂料是装入 分枝再翻 是一个明显的闪光 水合通道上, 完全匹配组件中要删除的 。 它不包含 由于包装会改变DOM 双方 正在比较中.

严格Mode双接力渲染,所以边界可以记起它的载荷 已经水合到缓存中 。 标记已经设定 之后 水分 成功, 从未有过 : 重试一个抛出的渲染, 然后先标记 使孩子们成为 虽然它已经奏效.

getServerSnapshot 现在读取 QueryCache.peek,它返回什么 缓存保存时没有打开它从未见过的查询记录 。 这么说吧 renderToString 发出真正的标记,其中边界使缓存在 组件,以及 idle 在那里没有人这样做。 双方同意无论哪种方式,这就是 属性 反应实际检查.

拒绝有效载荷的处理方式是理性的,而不是电文。 校长 不匹配重推, 因此您的错误边界会抓住它 挂载。 通过缓存报告版本或操作不匹配 onError 和树使上, 因为两者都通过查询修复 仅仅为自己取取 并空白一页 通过每次部署 比问题更严重 任何无法识别的重播.

还没做什么

德发道具.

同伴依赖关系

两种反应 财务报告和审定财务报表 @forge-go/client-core 是同龄人,而不是依赖关系。 两个 复制的 React 表示向错误的渲染器发送的钩子. 两份 核心表示两个模块级缓存,因此应用程序配置的客户端 它产生的钩子不是从同一个缺陷中读取的,而是从下面一层.

反应18和19都得到了支持和测试.

版本与发布记录

@forge-go/client-react 共发布 25 个版本,首次发布于 2026/08/07;过去 12 个月发布了 25 个版本。

版本发布日期距今
1.13.7latest2026/11/123 天前
1.13.62026/11/105 天前
1.13.52026/11/069 天前
1.13.42026/11/069 天前
1.13.32026/11/0610 天前
1.13.22026/10/2818 天前

关于 @forge-go/client-react 的常见问题

@forge-go/client-react 是什么?

对 Forge 客户端运行时间的回放绑定: 使用SyncExternalStore 来覆盖已规范的查询缓存

如何安装 @forge-go/client-react?

在项目目录运行 npm install @forge-go/client-react,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.0.0 || ^19.0.0)、@forge-go/client-core(^1.13.7)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@forge-go/client-react 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@forge-go/client-react 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@forge-go/client-react 可以商用吗?

@forge-go/client-react 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@forge-go/client-react 的下载量有多少?

根据 npm 官方下载统计,@forge-go/client-react 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,600 次,日均约 87 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@forge-go/client-react 还在维护吗?

最新版本 1.13.7 发布于 2026/11/12(3 天前);至今共发布 25 个版本,其中过去 12 个月发布了 25 个;首次发布于 2026/08/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。