alovajs / devtools

Editor devtools for alova.js
MIT License
9 stars 5 forks source link

Apis.xx.xx 作为参数时, 会隐式调用了toJSON , 造成apiPathKey 中包含 toJSON, 无法匹配到正确的接口 #38

Closed hi-cactus closed 1 week ago

hi-cactus commented 4 weeks ago

在React 中 若 将 Apis.xx.xx 作为组件参数时, 会隐式调用了toJSON , 造成apiPathKey 中包含 toJSON, 无法匹配到正确的接口


const createFunctionalProxy = (
  array: (string | symbol)[],
  alovaInstance: Alova<AlovaGenerics>,
  configMap: any
) => {
  // create a new proxy instance
  return new Proxy(function () {}, {
    get(_, property) {

       // 是否需要添加
       if (property === 'toJSON') return createFunctionalProxy(array, alovaInstance, configMap);

      // record the target property, so that it can get the completed accessing paths
      array.push(property);

      // always return a new proxy to continue recording accessing paths.
      return createFunctionalProxy(array, alovaInstance, configMap);
    },
  });
};
JOU-amjs commented 2 weeks ago

你是如何将Apis.xx.xx作为组件参数传入的,请提供下示例代码

hi-cactus commented 2 weeks ago

Hi @JOU-amjs 简化后的代码示例如下,


// hook 定义

export type ExtractValues<T> = T extends Method<infer U1> ? U1 : never;

export type ExtractResponse<T> = T extends AlovaGenerics<infer U1> ? U1 : never;

export const useRequestHook = <
  T extends (...args: any) => any,
  AG extends ExtractValues<ReturnType<T>>
>(
  methodHandler: T,
  params?: Parameters<T>[number]["params"],
  watchingStates?: AG["StatesExport"]["Watched"][],
  config?: WatcherHookConfig<AG> & {
    ignoreDateRange?: boolean;
  }
) => {
  const request = useWatcher<AG>(
    methodHandler({
      params: {
        ...(params ?? {}),
      },
    }),
    [...(watchingStates ?? [])],
    {
      // 其他配置
      middleware: async (ctx, next) => {
        // 业务处理
      },
      ...(config ?? {}),
    }
  );

  // 其他业务处理

  return request;
};

// 组件定义
export function TableCard(props) {
  const { data } = useRequestHook(
    props.api,
    {
            ...(props.apiConfig.params ?? {})
    }
  );

  return <div>data</div>;
}

// 使用

<TableCard
  api={Apis.xxx.xxx}
  apiConfig={{
    params: { id: 1 },
  }}
/>;
JOU-amjs commented 2 weeks ago

从自动生成的createApis.ts文件可以得知,我们是通过proxy的方式实现动态创建method实例的,也就是说当你调用函数时才会创建method实例,而Apis.xxx.xxx只是一个proxy函数而已,因此建议你传入组件时可以显式地定义一个函数:

<TableCard
  api={() => Apis.xxx.xxx(你的参数)}
  apiConfig={{
    params: { id: 1 },
  }}
/>;
hi-cactus commented 1 week ago

好主意, 我只需要传个函数包裹即可,

<TableCard
  api={() => Apis.xxx.xxx}
  apiConfig={{
    params: { id: 1 },
  }}
/>;