@_linked/react

中文文档
2.1.0发布于 2026/11/02MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 4076

QQ链接/ 核心的反应绑定

中文使用文档
文档目录20 节
  1. 安装
  2. 原生反应
  3. 使用量
  4. 设置套件导出
  5. linkedComponent(...)
  6. linkedSetComponent(...)
  7. linkedSetComponent(...) (直接查询格式)
  8. linkedSetComponent(...) (名称:数据正文格式)
  9. 导出您的组件 src/components/index.ts
  10. 渲染寿命周期和装载状态
  11. 反应
  12. 钩子
  13. 钩子还是组件?
  14. 在外边订阅 React
  15. 已链接的集页码 API
  16. 页:1
  17. 存储设置( 例如 : @_linked/rdf-mem-store (中文(简体) )
  18. 开始
  19. 发展
  20. 更改日志

链接/反应

反应约束 @_linked/core。 。 。 .

@_linked/react 获取链接的查询 @_linked/core是因为 Schema-Parameter化查询 DSL 并映射用于React组件的道具的顶级查询结果键.

查询API注释. 查询以 Shape.select(...) 返回一个 QueryBuilderA级 QueryBuilder 实值 懒惰 - 只有在你着火的时候 await 它或通过它 linkedComponent 编号 : linkedSetComponent旧的 Shape.query(...) 构建者名称已去; 使用 .select(...) 到处都是.

本套件提供:

  • linkedComponent(...) 财务报告和审定财务报表 linkedSetComponent(...) ——活性,有数据约束的组件
  • useLinkedQuery(...) 财务报告和审定财务报表 useLinkedSetQuery(...) 钩子在他们下面
  • LinkedComponentClass
  • useStyles(...), (中文(简体) ), useQueryContext(...)

部件和钩子 反应:经过任何突变后——局部,由数据集的更改回馈报告,或由您代码发布——每个被挂载的元件,其查询可以读取已修改后的数据回溯和还原,其他都无所作为. 见 反应。 。 。 .

安装

npm install @_linked/react @_linked/core react react-dom

支持反应 18 (E)^18.2.0)和反应19(^19.0.0) (中文(简体) ).

原生反应

从 @_linked/react/native 子路径而不是根 :

import {linkedComponent, linkedSetComponent, linkedShape} from '@_linked/react/native';

它输出的API与 @_linked/react (相同对象,不是副本). 导入它还设置 React 本地渲染默认值, 因为内置加载器和出错元素是 <svg> 元素,以及 React Industrial 上的崩溃:

  • LinkedComponentDefaults.loader数字 : <ActivityIndicator testID="linked-loader" />
  • LinkedComponentDefaults.errorElement数字 : <Text testID="linked-error" accessibilityRole="alert">Failed to load</Text>
  • LinkedInfinityLoader 做同样的 ActivityIndicator

它只在您的应用程序尚未设置时设置默认值. 实例道具和定义选项仍然与往常一样优先。 至少使用第一个子路径 @_linked/react 导入您的应用程序评分, 例如在 App.tsx。 。 。 .

react-native (单位:千美元)>=0.76)是一种可选的同伴依赖。 根条目从不导入它,所以网络应用不会安装它,也没有获得对等警告.

使用量

设置套件导出

import {
  linkedComponent,
  linkedSetComponent,
  linkedShape,
} from '@_linked/react';

linkedComponent(...)

linkedComponent(...) 用链接查询来包裹反应组件。 您通过一个以 Shape.select(...) ——归来 QueryBuilder 懒惰 包装器在时间点燃它 当你通过 of={{id: ...}},包装器将准备的查询应用于该主题,并将查询结果键作为道具注入到您的组件中.

const PersonCard = linkedComponent(
  Person.select((p) => p.name),
  ({name, source, _refresh}) => (
    <article>
      <h3>{name}</h3>
      <small>{source.id}</small>
      <button onClick={() => _refresh()}>Reload</button>
    </article>
  ),
);

// External API: pass `of` as a node reference (`{id: string}`), Shape, or QResult.
<PersonCard of={{id: 'https://example.org/p1'}} />;

包裹组件收到的道具 :

  • 查询结果道具:查询结果的所有顶级密钥都成为了直接道具(例如: name) (中文(简体) ).
  • source: 输入的已解析形状实例 of 主题.
  • _refresh(updatedProps?): 重运行查询 (_refresh())或复出前补丁本地查询结果道具(_refresh({...})) (中文(简体) ).
  • _refreshing数字 : true 当一个反射器在飞行中, 并且当前的数据仍然被解析出来.
  • 自定义道具:您通过到链接组件的任何附加道具都会作为正则转发.

定义选项( 第三个参数, 或配置对象的密钥) : loader, (中文(简体) ), errorElement, (中文(简体) ), notFoundElement (单主体查询回答时放弃) null;没有它,组件用空结果道具制造, name (查询模板的注册名称,默认为组件的函数名)和 reactive (单位:千美元)false 选择不自动调试的组件. loader, (中文(简体) ), errorElement 财务报告和审定财务报表 notFoundElement 也可以通过每个实例进行,并通过 LinkedComponentDefaults。 。 。 .

_refresh(updatedProps?) 链接组件

_refresh 注入包裹 linkedComponent(...) 提供功能.

  • _refresh() 重新运行查询,然后返回结果.
  • _refresh(updatedProps) 合并 updatedProps 输入当前结果,并立即返回(不先获取)。 编辑器生活在共享的活query缓存中,因此每个显示相同查询的组件都会看到;下回重写会覆盖它. 预装儿童(完整的结果通过) of编辑保留在该组件的局部,以及 _refresh() 让它自己去取.
  • updatedProps 仅用于查询结果键(例如 name, (中文(简体) ), active 从您的询问中, 父母不会通过普通的额外道具.

例用例:突变后乐观UI.

const PersonCard = linkedComponent(
  Person.select((p) => [p.name, p.active]),
  ({id, name, active, _refresh, title}) => (
    <div>
      <h4>{title}</h4>
      <span>{name}</span>
      <button
        onClick={async () => {
          // Patch query-result keys immediately (name/active/id/etc.)
          _refresh({active: !active}); // optimistic local query-result update
          await saveActiveFlag(id, !active); // your write call
          _refresh(); // optional: sync with store response
          // Not for parent custom props like `title`; those come from parent rerender.
        }}
      >
        Toggle active
      </button>
    </div>
  ),
);

linkedSetComponent(...)

使用 linkedSetComponent(...) 当您想要制作来源列表时.

linkedSetComponent(...) (直接查询格式)

const NameList = linkedSetComponent(
  Person.select((p) => p.name),
  ({linkedData}) => (
    <ul>
      {(linkedData || []).map((person) => (
        <li key={person.id}>{person.name}</li>
      ))}
    </ul>
  ),
);

linkedSetComponent(...) (名称:数据正文格式)

const personQuery = Person.select((p) => [p.name, p.hobby]);

const NameList = linkedSetComponent({persons: personQuery}, ({persons}) => (
  <ul>
    {persons.map((person) => (
      <li key={person.id}>{person.name}</li>
    ))}
  </ul>
));

两种格式都得到支持. 对于链接集包,外部 API 也是 of (可选). 内部变成 sources 用于包裹组件.

导出您的组件 src/components/index.ts

一个软件包向构建者提供其组件( Create Now 的拖放构建器) src/components/index.ts:按名称导出每个链接组件.

// src/components/index.ts
export {PersonCard} from './PersonCard.js';
export {NameList} from './NameList.js';

linked build 然后将软件包的组件索引写入 lib/esm/data/components.ttl旁边 shapes.ttl: 每个链接组件的导出名称、起始形状、查询形状和线条中的查询 格式 (单位:千美元)QueryBuilder.toJSON()作为犬科JSON。 发电机是 componentIndexTurtle(packageName, exports) 内 @_linked/react/utils/componentIndex。 。 。 .

  • 由 : linkedComponent 或者说 linkedSetComponent 已索引; 其他的都是 被忽略 。 以几个名称导出的一个组件是用最小名称命名的一个条目.
  • 定义时绑定的查询记录为: .for(getQueryContext('user')) 作为 上下文参考{"@ctx":"user"}, (中文(简体) ), .for('<iri>') 因为,IRI, .for(null) 作为 nullSubject在模块负载时设置的查询上下文(setQueryContext 模块顶级 指数进口)作为IRI记录解决.
  • 查询不序列化的组件被忽略,构建会打印一个命名它的警告.
  • 没有 src/components/index.ts没有文件. src/data/components.ttl 是保留名称: 写吧.

渲染寿命周期和装载状态

何时 LinkedStorage 已初始化,数据尚未预先装入 of数字 :

  • 第一个渲染: 返回装入元素( 已建入 SVG) .ld-loader,或 loader 从实例、定义选项或 LinkedComponentDefaults) (中文(简体) ).
  • 查询解析:组件以映射出查询结果道具重接.
  • 调试( N)_refresh(),或变化后的自动数据):当前数据仍然提供 _refreshing 实值 true 直到反应到达.
  • of 更改: 如果该主题已缓存在活水库中, 它会立即生成, 否则加载元素会显示到加载为止 .
  • 相同查询共享一个请求和一个缓存结果,各组成部分之间.

反应

两个组成部分,一个主题:

const TeamMembers = linkedComponent(Team.select((t) => t.members.name), ({members}) => (
  <ul>{members.map((m) => <li key={m.id}>{m.name}</li>)}</ul>
));
const TeamHeader = linkedComponent(Team.select((t) => [t.name, t.members.size()]), ({name, members}) => (
  <h2>{name} ({members})</h2>
));

await Team.update({members: {add: [{id: personId}]}}).for({id: teamId});
// → TeamHeader and TeamMembers refetch and rerender. A PersonCard for someone else does not.

如何运作:核心维持一个活平仓(见核心) 生活厨房指南) (中文(简体) ). 每个挂载的组件都是其查询模板的活实例;模板的依赖性——即它所读取的,它过滤的或种类,它所触及的形状——是从查询中计算一次. 每一次更改都与它写的东西和它所触及的节点正常化,而商店完全反射出可以受到影响的事例,通过节点ID可以分辨,在无法分辨的地方则在模板上宽.

更改源, 所有自动设置 :

  • 本地变异 ——每个 await Shape.update/create/delete(...) 在应用中, exec(target) 包含.
  • 数据集的更改种子 ——执行的数据集 IDataset.subscribeChanges(listener) 报告在别处(另一个客户端,服务器任务)所做的更改,作为突变的DSL-JSON及其结果,或者作为预计算效果.
  • 你自己的交通工具 —— 说 publishChange({mutation, result}) 或者说 publishChange({effects}) 从应用程序代码(从 @_linked/react) (中文(简体) ).
  • 手动 —— 说 invalidate(Team), (中文(简体) ), invalidate({id}), (中文(简体) ), invalidate(query) 或者说 _refresh()。 。 。 .

一个组件可以选择退出 {reactive: false};这适用于其查询模板,即使用该精确查询的每个组件或钩子。 部件和钩子在React BestMode下是安全的. 通过的结果对象 of 由预装的家长(preloadFor)并不单独订阅;它通过父母保持新鲜,父母的询问包括孩子的田地.

钩子

组件建立在两个钩子上,为组件形状不适合的大小写导出 : 一个组件中的几个查询,一个取决于本地状态的查询(一个搜索框,一个选定的标签),有条件的取取取,一个内线计数,或者没有的数据 of 主题.

import {useLinkedQuery, useLinkedSetQuery} from '@_linked/react';

function TeamPage({teamId}: {teamId: string}) {
  const team = useLinkedQuery(Team.select((t) => [t.name, t.members.size()]), {id: teamId});
  const total = useLinkedQuery(Team.select().toCount());
  const [q, setQ] = useState('');
  const results = useLinkedSetQuery(
    Person.select((p) => p.name).where((p) => p.name.contains(q)).limit(20),
    undefined,
    {enabled: q.length > 1},
  );
  if (team.loading) return <Spinner />;
  // team.data.name, team.data.members, team.refreshing, team.notFound, team.refresh(), team.patch({...})
  // results.data, results.page.next() / previous() / set(i) / setLimit(n)
}
  • useLinkedQuery(query, of?, options?) → {data, loading, refreshing, error, notFound, refresh, patch}。 。 。 . of 实值 {id},形状,或结果对象;在构建者已经绑定时可选(.for(id), (中文(简体) ), .for(getQueryContext('user')))或是一个计数/任务. loading 表示还没有数据; refreshing 表示有数据存在,获取正在飞行中.
  • useLinkedSetQuery(query, of?, options?) - 同样的加法 page: {next, previous, set, setLimit, index, limit}。 。 。 . of 是一个 ShapeSet 或数组 {id}/形状/结果对象.
  • 选项 : enabled (默认) true, (中文(简体) ), reactive, (中文(简体) ), name。 。 。 .

getLiveQueryStore().templates() 列出每个已注册的查询模板(组成部分在定义中登记其内容),以及 getLiveQueryStore().prepare() 急切计算它们的依赖性——一个app可以点火的查询列表,以便数据库调用.

钩子还是组件?

反应方式是相同的:挂起的钩子和挂起的组件都记录他们的查询的活实例,在匹配变化后,两者都进行回溯. 区别在于 不渲染而发现,其中只有链接的组件提供:

  • preloadFor(Component) - 父母读取孩子的静态 query 并在同一请求中加载其字段.
  • 包登记 ——构件按外形登记.
  • 模板登记册 ——其查询模板被固定在定义上,所以 templates() 编号 : prepare() 从应用程序开始列出它。 赤钩子的模板仅在挂载时列出,闲用时会被丢出.

使用 linkedComponent 编号 : linkedSetComponent 默认: 一个组件, 一个查询, 一个主题通过 of. 当形状不合适时到达钩子——一个组件中的若干查询,这个查询取决于当地状态,有条件取取取(enabled),一个内行计数或存在检查,数据没有 of 主体,或包接按自身条件构成的第三方组件。 基于钩的组件无法发现: 它没有静态 query,所以它不能是一个 preloadFor 目标,不在软件包登记册中,不能通过列出组件和它们需要的数据的工具提供可连接组件。 任何应该可以发现的东西——一个查询,一个主题通过 of 属于 linkedComponent。 。 。 .

在外边订阅 React

同一商店的工作没有反应: query.live() 返回控点为 state, (中文(简体) ), subscribe(cb), (中文(简体) ), refresh(), (中文(简体) ), patch() 财务报告和审定财务报表 close(),以及 await live 以第一个结果解决。 见核心 生活厨房指南。 。 。 .

已链接的集页码 API

何时 linkedSetComponent(...) 有限制(明确查询限制或默认限制),包裹道具包括:

  • query.nextPage()
  • query.previousPage()
  • query.setPage(pageIndex)
  • query.setLimit(limit) (也移回第一页)

没有公众 setOffset(...) 在反应查询控制器中; 使用 setPage, (中文(简体) ), nextPage,或 previousPage。 。 。 .

示例

import React from 'react';

const PeopleList = linkedSetComponent(
  Person.select((p) => [p.name]).limit(5),
  ({linkedData = [], query}) => {
    const [page, setPage] = React.useState(0);

    return (
      <section>
        <ul>
          {linkedData.map((person) => (
            <li key={person.id}>{person.name}</li>
          ))}
        </ul>

        <div>
          <button
            onClick={() => {
              query?.previousPage();
              setPage((p) => Math.max(0, p - 1));
            }}
          >
            Previous
          </button>

          <span>Page {page + 1}</span>

          <button
            onClick={() => {
              query?.nextPage();
              setPage((p) => p + 1);
            }}
          >
            Next
          </button>

          <label>
            Page size
            <select
              defaultValue="5"
              onChange={(e) => {
                const nextLimit = Number(e.target.value);
                query?.setLimit(nextLimit);
                query?.setPage(0);
                setPage(0);
              }}
            >
              <option value="5">5</option>
              <option value="10">10</option>
              <option value="25">25</option>
            </select>
          </label>
        </div>
      </section>
    );
  },
);

页:1

  • 此软件包取决于 @_linked/core 查询 APIs 、 其活的- query 商店以及 preloadFor(...) 编号 : BoundComponent 行为从核心.
  • @_linked/react 本身不提供 RDF 存储; 使用存储包并设置默认存储 LinkedStorage (例如 @_linked/rdf-mem-store) (中文(简体) ).

存储设置( 例如 : @_linked/rdf-mem-store(中文(简体) )

本地内存设置, 请注册 @_linked/rdf-mem-store 作为默认存储 :

import {LinkedStorage} from '@_linked/core';
import {InMemoryStore} from '@_linked/rdf-mem-store';

LinkedStorage.setDefaultStore(new InMemoryStore());

开始

  • 添加 setOffset 改为 linkedSetComponent 查询控制器.

发展

npm run build
npm test

更改日志

见 变动情况。 。 。 .

版本与发布记录

@_linked/react 共发布 40 个版本,首次发布于 2026/02/12;过去 12 个月发布了 40 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
2.1.0latest2026/11/025 天前
2.0.52026/10/2810 天前
2.0.42026/10/2513 天前
2.0.32026/10/2414 天前
2.0.22026/10/1919 天前
2.0.12026/10/0929 天前

其他发布通道:next → 1.4.2-next.20260713192413。

关于 @_linked/react 的常见问题

@_linked/react 是什么?

QQ链接/ 核心的反应绑定

如何安装 @_linked/react?

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

@_linked/react 支持 TypeScript 吗?

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

@_linked/react 支持 ESM 还是 CommonJS?

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

@_linked/react 可以商用吗?

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

@_linked/react 的下载量有多少?

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

@_linked/react 还在维护吗?

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