Skip to content

API Hook 工厂 ​

两个工厂把现有服务对象的异步方法转换为稳定 Hook 名称,例如 getUser 变成 useGetUser。在渲染之外创建 Hook 集合。它们保留服务 this,扫描自身及原型链方法,同名属性以最近的定义为准。

工厂 / 工具契约
createExecuteApiHooks({ api })各 Hook 接受执行器选项,返回状态和 execute(...原参数): Promise<PromiseState>;不自动调用。
createQueryApiHooks({ api })各 Hook 接受受控查询选项(query、attributes、autoExecute),调用 method(query, attributes, abortController)。
methodNameToHookName(name)添加 use 并大写首字符;空名称抛错。
collectMethods(obj)返回绑定方法的 Map:自身及原型链上的函数属性,最近的定义优先。跳过 constructor、Object.prototype 和访问器,因此收集时不会执行 getter。

只有 Hook 设置 appendAbortController: true 时,执行 Hook 才传入 controller:方法以 method(...params, abortController) 调用,@api 方法无论 controller 落在哪个位置都能识别,因此替换、中止或卸载执行会取消其请求。方法带可选尾参数时不要开启,否则 controller 会占据参数位置;这时可在自己的服务方法中包装它。查询工厂自动转发 attributes 和 controller。两种 execute 都解析为最终状态,从不拒绝。

APIHooks、QueryAPIHooks、UseApiMethodExecuteReturn、HookName、ApiHooksMapping、ApiMethod、QueryMethod、FunctionParameters、FunctionReturnType、IsPromiseFunction 描述编译期映射。运行时只检查属性是不是函数,不检查其是否真正返回 Promise。由 getter 提供的函数不会转换为 Hook。只传入可信服务对象。取消、回调、过期结果和卸载规则见 共享执行器契约。

6.0 变更

移除了 onBeforeExecute 和 OnBeforeExecuteCallback 类型;UseApiMethodExecuteOptions 去掉了第一个类型参数(TArgs)。查询 Hook 从你的状态接收 query,不再使用 initialQuery/setQuery/getQuery。collectMethods 只接受一个参数,getter 提供的函数不再变成 Hook。

完整示例 ​

tsx
import { createExecuteApiHooks } from '@ahoo-wang/fetcher-react';

const hooks = createExecuteApiHooks({
  api: {
    async double(value: number) {
      return value * 2;
    },
  },
});

export function Calculator() {
  const { execute, result, error } = hooks.useDouble();
  return (
    <section>
      <button
        onClick={async () => {
          const state = await execute(21);
          if (state.status === 'success') console.log(state.result);
        }}
      >
        Calculate
      </button>
      <output>{result}</output>
      {error && <p role="alert">{error.message}</p>}
    </section>
  );
}

公开签名与类型 ​

以下签名按当前根入口可达声明核对。? 表示可省略;泛型/接口只约束编译期,继承项与关联类型可从 符号索引 定位。运行时默认值和失败行为以本页上文为准。

methodNameToHookName ​

ts
export function methodNameToHookName(methodName: string): string;

packages/react/src/api/apiHooks.ts:15

collectMethods ​

ts
export function collectMethods<T extends (...args: any[]) => Promise<any>>(
  obj: object,
): Map<string, T>;

packages/react/src/api/apiHooks.ts:28

CreateApiHooksOptions ​

ts
export interface CreateApiHooksOptions<API extends Record<string, any>> {
  api: API;
}

packages/react/src/api/apiHooks.ts:50

HookName ​

ts
export type HookName<K extends string> = `use${Capitalize<K>}`;

packages/react/src/api/apiHooks.ts:54

IsPromiseFunction ​

ts
export type IsPromiseFunction<T> = T extends (...args: any[]) => Promise<any>
  ? true
  : false;

packages/react/src/api/apiHooks.ts:56

FunctionParameters ​

ts
export type FunctionParameters<T> = T extends (...args: infer P) => Promise<any>
  ? P
  : never;

packages/react/src/api/apiHooks.ts:60

FunctionReturnType ​

ts
export type FunctionReturnType<T> = T extends (
  ...args: any[]
) => Promise<infer R>
  ? Awaited<R>
  : never;

packages/react/src/api/apiHooks.ts:64

ApiMethod ​

ts
export type ApiMethod<TArgs extends any[] = any[], TReturn = any> = (
  ...args: TArgs
) => Promise<TReturn>;

packages/react/src/api/apiHooks.ts:70

QueryMethod ​

ts
export type QueryMethod<Q = any, TReturn = any> = (
  query: Q,
  attributes?: Record<string, any>,
  abortController?: AbortController,
) => Promise<TReturn>;

packages/react/src/api/apiHooks.ts:75

ApiHooksMapping ​

ts
export type ApiHooksMapping<
  API extends Record<string, any>,
  MethodType extends (...args: any[]) => Promise<any>,
  HookType,
> = {
  [
    K in keyof API as API[K] extends MethodType ? HookName<string & K> : never
  ]: API[K] extends MethodType ? HookType : never;
};

packages/react/src/api/apiHooks.ts:81

createExecuteApiHooks ​

ts
export function createExecuteApiHooks<
  API extends Record<string, any>,
  E = FetcherError,
>(options: CreateExecuteApiHooksOptions<API>): APIHooks<API, E>;

packages/react/src/api/createExecuteApiHooks.ts:100

CreateExecuteApiHooksOptions ​

ts
export interface CreateExecuteApiHooksOptions<
  API extends Record<string, any>,
> extends CreateApiHooksOptions<API> {}

packages/react/src/api/createExecuteApiHooks.ts:31

UseApiMethodExecuteOptions ​

ts
export interface UseApiMethodExecuteOptions<
  TData = any,
  E = FetcherError,
> extends UseExecutePromiseOptions<TData, E> {
  /** @default false */
  appendAbortController?: boolean;
}

packages/react/src/api/createExecuteApiHooks.ts:35

UseApiMethodExecuteReturn ​

ts
export type UseApiMethodExecuteReturn<
  TArgs extends any[],
  TData,
  E = FetcherError,
> = Omit<UseExecutePromiseReturn<TData, E>, 'execute'> & {
  execute: (...params: TArgs) => Promise<PromiseState<TData, E>>;
};

packages/react/src/api/createExecuteApiHooks.ts:47

APIHooks ​

ts
export type APIHooks<API extends Record<string, any>, E = FetcherError> = {
  [
    K in keyof API as API[K] extends ApiMethod ? HookName<string & K> : never
  ]: API[K] extends ApiMethod
    ? (
        options?: UseApiMethodExecuteOptions<FunctionReturnType<API[K]>, E>,
      ) => UseApiMethodExecuteReturn<
        FunctionParameters<API[K]>,
        FunctionReturnType<API[K]>,
        E
      >
    : never;
};

packages/react/src/api/createExecuteApiHooks.ts:56

createQueryApiHooks ​

ts
export function createQueryApiHooks<
  API extends Record<string, any>,
  E = FetcherError,
>(options: CreateQueryApiHooksOptions<API>): QueryAPIHooks<API, E>;

packages/react/src/api/createQueryApiHooks.ts:69

CreateQueryApiHooksOptions ​

ts
export interface CreateQueryApiHooksOptions<
  API extends Record<string, any>,
> extends CreateApiHooksOptions<API> {}

packages/react/src/api/createQueryApiHooks.ts:24

UseApiMethodQueryOptions ​

ts
export interface UseApiMethodQueryOptions<
  Q,
  TData = any,
  E = FetcherError,
> extends Omit<UseQueryOptions<Q, TData, E>, 'execute'> {
  attributes?: Record<string, any>;
}

packages/react/src/api/createQueryApiHooks.ts:28

QueryAPIHooks ​

ts
export type QueryAPIHooks<API extends Record<string, any>, E = FetcherError> = {
  [
    K in keyof API as API[K] extends QueryMethod ? HookName<string & K> : never
  ]: API[K] extends QueryMethod<infer Q, infer R>
    ? (options?: UseApiMethodQueryOptions<Q, R, E>) => UseQueryReturn<R, E>
    : never;
};

packages/react/src/api/createQueryApiHooks.ts:37

相关专题 ​

Fetcher 请求 Hook · Promise 与查询状态 · 防抖执行 · 存储与事件订阅 · 安全 Hook 与路由守卫 · 最新值与稳定值

基于 Apache License 2.0 发布。