v3.9.3
What's Changed
🎉 New Features
- feat(react): add createExecuteApiHooks utility for generating API method hooks by @Ahoo-Wang in #985
- feat(api): add appendAbortController option to API hooks by @Ahoo-Wang in #986
createExecuteApiHooks
🚀 自动类型安全 API Hooks 生成 - 从 API 对象自动生成完全类型化的 React hooks,具有自动方法发现、类方法支持和高级执行控制。
createExecuteApiHooks 函数自动发现 API 对象中的所有函数方法(包括类实例的原型链),并使用命名模式 use{首字母大写的方法名} 创建相应的 React hooks。每个生成的 hook 都提供完整的状态管理、错误处理,并支持具有类型安全参数访问的自定义执行回调。
主要特性:
- 自动方法发现:遍历对象属性和原型链
- 类型安全 Hook 生成:参数和返回类型的完整 TypeScript 推断
- 类方法支持:处理静态方法和具有
this绑定的类实例 - 执行控制:
onBeforeExecute回调用于参数检查/修改和中止控制器访问 - 自定义错误类型:支持指定超出默认
FetcherError的错误类型
import { createExecuteApiHooks } from '@ahoo-wang/fetcher-react';
import { api, get, post, patch, path, body, autoGeneratedError } from '@ahoo-wang/fetcher-decorator';
// 使用装饰器定义您的 API 服务
import { api, get, post, patch, path, body, autoGeneratedError } from '@ahoo-wang/fetcher-decorator';
@api('/users')
class UserApi {
@get('/{id}')
getUser(@path('id') id: string): Promise<User> {
throw autoGeneratedError(id);
}
@post('')
createUser(@body() data: { name: string; email: string }): Promise<User> {
throw autoGeneratedError(data);
}
@patch('/{id}')
updateUser(@path('id') id: string, @body() updates: Partial<User>): Promise<User> {
throw autoGeneratedError(id, updates);
}
}
const userApi = new UserApi();
// 生成类型安全的 hooks
const apiHooks = createExecuteApiHooks({ api: userApi });
function UserComponent() {
// Hooks 自动生成,具有正确的类型
const { loading: getLoading, result: user, error: getError, execute: getUser } = apiHooks.useGetUser();
const { loading: createLoading, result: createdUser, error: createError, execute: createUser } = apiHooks.useCreateUser({
onBeforeExecute: (abortController, args) => {
// args 完全类型化为 [data: { name: string; email: string }]
const [data] = args;
// 如果需要,可以就地修改参数
data.email = data.email.toLowerCase();
// 访问中止控制器以进行自定义取消
abortController.signal.addEventListener('abort', () => {
console.log('用户创建已取消');
});
},
});
const handleFetchUser = (userId: string) => {
getUser(userId); // 完全类型化 - 仅接受字符串参数
};
const handleCreateUser = (userData: { name: string; email: string }) => {
createUser(userData); // 完全类型化 - 仅接受正确的数据形状
};
return (
<div>
<button onClick={() => handleFetchUser('123')}>
获取用户
</button>
{getLoading && <div>正在加载用户...</div>}
{getError && <div>错误: {getError.message}</div>}
{user && <div>用户: {user.name}</div>}
<button onClick={() => handleCreateUser({ name: 'John', email: 'john@example.com' })}>
创建用户
</button>
{createLoading && <div>正在创建用户...</div>}
{createError && <div>错误: {createError.message}</div>}
{createdUser && <div>已创建: {createdUser.name}</div>}
</div>
);
}Full Changelog: v3.9.2...v3.9.3