v0.9:DevTools、Resource.extend 与清理遗留 API
本次发布聚焦于开发者体验:在开发模式下显示的 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',
});
破坏性变更:
- 移除所有 /next 导出
- 移除 makeCacheProvider
- DELETE -> INVALIDATE action 类型
- 不再支持遗留 schema
- Schema 序列化器必须支持函数调用
- Action 类型加上 'rdc' 前缀
Resource.extend() (自 0.5 起)
Resource.extend() 提供了三种强大的方式来自定义 resource。 51b4b0d
添加新的 endpoint
const UserResource = createResource({
path: '/users/:id',
schema: User,
}).extend('current', {
path: '/users/current',
});
覆盖已有的 endpoint
const CachedArticleResource = ArticleResource.extend({
getList: {
dataExpiryLength: 10 * 60 * 1000, // 10 minutes
},
});
从基础 endpoint 派生
const IssueResource = createResource({
path: '/issues/:id',
schema: Issue,
}).extend(Base => ({
byRepo: Base.getList.extend({
path: '/repos/:owner/:repo/issues',
}),
}));
Controller 方法
controller.expireAll() (自 0.3 起)
将所有匹配的响应标记为过时,在继续显示现有数据的同时触发后台重新获取。 #2802
// Mark all article lists as stale - they'll refetch when rendered
controller.expireAll(ArticleResource.getList);
这与会完全移除数据的 invalidateAll() 不同。expireAll() 会继续显示缓存的数据,同时在后台获取最新数据。
controller.fetchIfStale() (自 0.4 起)
仅在数据被视为过时时才发起获取;否则返回缓存的数据。 #2804
// Perfect for prefetching - won't overfetch fresh data
const resolveData = async (controller, { owner, repo }) => {
await controller.fetchIfStale(IssueResource.getList, { owner, repo });
};
DevTools 改进
DevTools 按钮
开发模式下现在会显示一个浮动按钮,用于快速打开 Redux DevTools 扩展。 #2803
通过 devButton prop 配置或禁用它:
// Disable the button
<CacheProvider devButton={null}>
<App />
</CacheProvider>
// Position it differently
<CacheProvider devButton="top-right">
<App />
</CacheProvider>
持久化的历史记录
即使页面加载时 DevTools 未打开,也不再丢失历史记录。 2d2e941
更好的状态跟踪
由于 React 18 会对更新进行批处理,真实状态有时会由多个 action 一起更新。当 devtools 打开时,一个影子状态会准确反映每个 action 带来的变化,便于调试。 c9ca31f
Endpoint 属性可见
Endpoint 的属性现在可以在 devtool 检查器中完整查看。 a7da00e
Collection 增强
FormData 参数筛选 (自 0.4 起)
Collection 现在可以基于 FormData 参数进行筛选。f95dbc6
ctrl.fetch(getPosts.push, { group: 'react' }, new FormData(e.currentTarget));
如果 FormData 中包含 author 字段,新创建的条目会被正确地添加到按该作者筛选的 collection 中。
paginationField (自 0.7 起)
使用 paginationField 轻松支持分页。 c8c557
const TodoResource = createResource({
path: '/todos/:id',
schema: Todo,
paginationField: 'page',
});
// Fetches page 2 and appends to the collection
ctrl.fetch(TodoResource.getList.getPage, { page: '2' });
其他改进
- 为 ErrorBoundary 添加
className,为 AsyncBoundary 添加errorClassName#2785 - 新增
getDefaultManagers()导出,用于显式控制 manager #2791 - 用 UniversalSuspense + BackupLoading 取代 BackupBoundary #2803
- Entity.process() 的第四个参数接收 endpoint 的
args(自 0.7 起) a8936f5 - Collection 新增
nonFilterArgumentKeys,用于在筛选时排除 sort/order 参数 (自 0.7 起) 318df89
迁移指南
本次升级需要同时更新所有包的版本。
- NPM
- Yarn
- pnpm
- esm.sh
npm install --save @data-client/react@^0.9.0 @data-client/rest@^0.9.0 @data-client/test@^0.9.0 @data-client/img@^0.9.0 @data-client/hooks@^0.9.0
yarn add @data-client/react@^0.9.0 @data-client/rest@^0.9.0 @data-client/test@^0.9.0 @data-client/img@^0.9.0 @data-client/hooks@^0.9.0
pnpm add @data-client/react@^0.9.0 @data-client/rest@^0.9.0 @data-client/test@^0.9.0 @data-client/img@^0.9.0 @data-client/hooks@^0.9.0
<script type="importmap">
{
"imports": {
"@data-client/react": "https://esm.sh/@data-client/react@^0.9.0",
"@data-client/rest": "https://esm.sh/@data-client/rest@^0.9.0",
"@data-client/test": "https://esm.sh/@data-client/test@^0.9.0",
"@data-client/img": "https://esm.sh/@data-client/img@^0.9.0",
"@data-client/hooks": "https://esm.sh/@data-client/hooks@^0.9.0"
}
}
</script>
移除 /next 导出
所有 /next 子路径导出都已移除。之前位于 /next 中的功能现在是标准导出。f65cf83
import { useController } from '@data-client/react/next';
import { useController } from '@data-client/react';
移除 makeCacheProvider
请直接把 provider 组件传给 makeRenderDataClient。 #2787
import { makeCacheProvider } from '@data-client/react';
const renderDataClient = makeRenderDataClient(makeCacheProvider);
import { CacheProvider } from '@data-client/react';
const renderDataClient = makeRenderDataClient(CacheProvider);
DELETE -> INVALIDATE action 类型
为了更清晰,DELETE action 类型已重命名为 INVALIDATE。 #2784
import { DELETE_TYPE } from '@data-client/react';
import { INVALIDATE_TYPE } from '@data-client/react';
不再支持遗留 schema
对遗留 schema 的所有支持都已移除。请确保你使用的是当前的 Entity 类。#2784
- 移除了
entity.expiresAt - 移除了所有为向后兼容而保留的 Entity 覆盖
Schema 序列化器必须支持函数调用
Schema 序列化器现在必须支持函数调用。Date 不再能直接使用。#2795
class MyEntity extends Entity {
createdAt = new Date();
static schema = {
createdAt: Date,
};
}
class MyEntity extends Entity {
createdAt = new Date();
static schema = {
createdAt: (iso: string) => new Date(iso),
};
}
或者,使用 Temporal:
import { Temporal } from 'temporal-polyfill';
class MyEntity extends Entity {
createdAt = Temporal.Instant.fromEpochSeconds(0);
static schema = {
createdAt: Temporal.Instant.from,
};
}
Action 类型加上 'rdc' 前缀
为了更好的命名空间隔离,所有 action 类型现在都带有 'rdc' 前缀。 #2781
receive -> set action 名称
所有 'receive' action 名称都已重命名为 'set'。 #2782
import { ReceiveAction, RECEIVE_TYPE } from '@data-client/react';
controller.receive(endpoint, args, response);
import { SetAction, SET_TYPE } from '@data-client/react';
controller.set(endpoint, args, response);
简化的 Middleware API
Middleware 不再以解构属性的形式接收 controller,而是直接接收 controller。#2786
class LoggingManager implements Manager {
getMiddleware = (): Middleware => ({ controller }) => next => async action => {
console.log('before', action, controller.getState());
await next(action);
console.log('after', action, controller.getState());
};
cleanup() {}
}
class LoggingManager implements Manager {
getMiddleware = (): Middleware => controller => next => async action => {
console.log('before', action, controller.getState());
await next(action);
console.log('after', action, controller.getState());
};
cleanup() {}
}
getDefaultManagers()
CacheProvider 元素不再共享默认的 manager。请使用 getDefaultManagers() 进行显式控制。
#2791
import { getDefaultManagers, CacheProvider } from '@data-client/react';
const managers = getDefaultManagers();
<CacheProvider managers={managers}>
<App />
</CacheProvider>
升级支持
一如往常,如果你遇到任何问题或有疑问,欢迎加入我们的 或提交 bug
