跳到主要内容

5 篇博文 含有标签「REST」

Representational state transfer: HTTP based APIs

查看所有标签

v0.18:Scalar、类型化文件下载、过滤感知的 Collection

· 阅读需 12 分钟
Nathaniel Tucker
Creator of Reactive Data Client

v0.18 聚焦于三件事:对随请求上下文变化的值进行更丰富的数据建模、更简单的类型化下载,以及更贴近真实 API 过滤条件的集合匹配。

新特性:

其他改进:

Fixtures
▶api/Company
import { Collection, Entity, RestEndpoint, Scalar } from '@data-client/rest';

export class Company extends Entity {
  id = '';
  name = '';
  price = 0;
  pct_equity = 0;
  shares = 0;
}

const PortfolioScalar = new Scalar({
  lens: args => args[0]?.portfolio,
  key: 'portfolio',
  entity: Company,
});
Company.schema = {
  pct_equity: PortfolioScalar,
  shares: PortfolioScalar,
};

export const getCompanies = new RestEndpoint({
  path: '/companies',
  searchParams: {} as { portfolio: string },
  // `portfolio` is a lens, not a filter — the returned Company list is the same
  // regardless of lens. Dropping it from `argsKey` collapses every portfolio to
  // one Collection pk, so `Collection.queryKey()` finds the list on every
  // switch and `useSuspense` reuses it without refetching.
  schema: new Collection([Company], { argsKey: () => ({}) }),
});

export const getPortfolioColumns = new RestEndpoint({
  path: '/companies/columns',
  searchParams: {} as { portfolio: string },
  schema: new Collection([PortfolioScalar], {
    argsKey: ({ portfolio }: { portfolio: string }) => ({ portfolio }),
  }),
});
▶CompanyGrid
▶PortfolioGrid
结果
Store▶

这个示例展示了同一批 Company 实体通过不同的投资组合视角进行渲染。稳定的 Entity 字段会被复用,而随视角变化的值则从独立的 Scalar 单元格中选取。

破坏性变更:

**在使用 AI 智能体?**安装迁移 skill——它会运行 codemod,为依赖参数的 schema 注册 argsKey,并处理 codemod 无法覆盖的情况(类字段、动态方法赋值、SFC <script> 块、自定义辅助函数):

npx skills add reactive/data-client --skill data-client-v0.18-migration

否则,直接运行 codemod——它覆盖了常见情况:

npx jscodeshift -t https://dataclient.io/codemods/v0.18.js --extensions=ts,tsx,js,jsx src/

v0.16:并行获取、Collection.move、Lazy

· 阅读需 13 分钟
Nathaniel Tucker
Creator of Reactive Data Client

新特性:

其他改进:

Collection.move 让你能够用一次操作轻松地在多个 Collection 之间移动实体:

import { useController } from '@data-client/react';
import { TaskResource, type Task } from './TaskResource';

export default function TaskCard({ task }: { task: Task }) {
  const handleMove = () => ctrl.fetch(
    TaskResource.getList.move,
    { id: task.id },
    { id: task.id, status: task.status === 'backlog' ? 'in-progress' : 'backlog' },
  );
  const ctrl = useController();
  return (
    <div className="listItem">
      <span style={{ flex: 1 }}>{task.title}</span>
      <button onClick={handleMove}>
        {task.status === 'backlog' ? '\u25bc' : '\u25b2'}
      </button>
    </div>
  );
}
结果

破坏性变更:

使用自动化 codemod 升级,它涵盖所有破坏性变更:

npx jscodeshift -t https://dataclient.io/codemods/v0.16.js --extensions=ts,tsx,js,jsx src/

v0.10:一致的 null 处理、URL 工具函数

· 阅读需 4 分钟
Nathaniel Tucker
Creator of Reactive Data Client

本次发布聚焦于一致性和可扩展性。null 处理现在在所有 schema 类型中保持统一,使数据转换更可预测。新的 URL 工具函数支持自定义 URL 构造和搜索参数编码。

class MyEndpoint<O extends RestGenerics = any> extends RestEndpoint<O> {
searchToString(searchParams) {
// Use qs library for complex nested object encoding
return qs.stringify(searchParams);
}
}
迁移指南

破坏性变更:

其他改进:

v0.9:DevTools、Resource.extend 与清理遗留 API

· 阅读需 8 分钟
Nathaniel Tucker
Creator of Reactive Data Client

本次发布聚焦于开发者体验:在开发模式下显示的 devtools 按钮、更好的 DevTools 历史记录,以及 controller.expireAll() 和 controller.fetchIfStale() 等新的 controller 方法。

Resource.extend() 提供了三种强大的方式来自定义 resource——添加新的 endpoint、覆盖已有的 endpoint,或从基础 endpoint 派生。

const UserResource = createResource({
path: '/users/:id',
schema: User,
}).extend('current', {
path: '/users/current',
});
迁移指南

破坏性变更:

v0.2 Controller.fetch、异步 getHeaders、Collection

· 阅读需 6 分钟
Nathaniel Tucker
Creator of Reactive Data Client

Collection 让数组和对象可以通过 push 或 unshift 新成员来轻松扩展。它的名字来自 Backbone Collections。

Collection 现在是 Resource.getList 的默认 schema。

import { useController } from '@data-client/react';
import { TodoResource } from './TodoResource';

export default function CreateTodo({ userId }: { userId: number }) {
  const ctrl = useController();
  const handleKeyDown = async e => {
    if (e.key === 'Enter') {
      ctrl.fetch(TodoResource.getList.push, {
        userId,
        title: e.currentTarget.value,
        id: Math.random(),
      });
      e.currentTarget.value = '';
    }
  };
  return (
    <div className="listItem nogap">
      <label>
        <input type="checkbox" name="new" checked={false} disabled />
        <input type="text" onKeyDown={handleKeyDown} />
      </label>
    </div>
  );
}
结果

升级相当简单,因为我们引入了 @data-client/rest/next 和 @data-client/react/next,以便渐进式地采用本版本中变更的新 API。这使得实际的升级只是简单地重命名一下导入路径。

其他亮点包括

完整细节请继续阅读: