import { dehydrate, HydrationBoundary } from '@tanstack/react-query';

import getQueryClient from '@/lib/react-query/getQueryClient';

export async function RQBoundary<T>({
  children,
  queryKey,
  fn,
}: {
  children: React.ReactNode;
  queryKey: string[];
  fn: () => Promise<T>;
}) {
  const queryClient = getQueryClient();

  await queryClient.prefetchQuery({
    queryKey,
    queryFn: fn,
  });
  const dehydratedState = dehydrate(queryClient);
  return (
    <HydrationBoundary state={dehydratedState}>{children}</HydrationBoundary>
  );
}


export default function Page() {
  return (
    ...
      <RQBoundary queryKey={['posts']} fn={getPosts}>
        <PostTable />
      </RQBoundary>
    ...
  );
}

要在Reaction-Query中配置SSR,我们将如上所述创建和使用RQ边界.

但是,FETCH函数有时会接收需要参数的函数.在本例中,由于RQBoundary组件的类型为fn: () => Promise<T>;,因此向其传递带有参数的函数将导致以下错误.

Type '(id: string) => Promise<ResponsePost>' is not assignable to type '() => Promise<ResponsePost>'. Target signature provides too few arguments. Expected 1 or more, but got 0.个 如何创建既可以向存在的函数传递参数,也可以向不存在的函数传递参数的组件?

export async function RQParamsBoundary<T>({
  children,
  queryKey,
  fn,
  params
}: {
  params:string
  children: React.ReactNode;
  queryKey: string[];
  fn: (id:string) => Promise<T>;
}) {
  const queryClient = getQueryClient();

  await queryClient.prefetchQuery({
    queryKey,
    queryFn: ()=>fn(params),
  });
  const dehydratedState = dehydrate(queryClient);
  return (
    <HydrationBoundary state={dehydratedState}>{children}</HydrationBoundary>
  );
}

我不认为创建另一个这样的组件是个好主意.

推荐答案

为此,您可以使用预期的两个props 签名的联合(一个签名fn不带任何参数,没有params,另一个签名fn需要字符串参数,params是字符串),然后在调用点使用泛型类型参数在这两个变量之间进行 Select .下面是一个简单的例子,go 掉了不相关的东西:

type RQBoundaryParams<T> =
    | {
        fn(id: string): Promise<T>;
        params: string;
    }
    | {
        fn(): Promise<T>;
    };
export function RGBoundary<T, Params extends RQBoundaryParams<T>>(props: Params): React.ReactNode {
    if ("params" in props) {
        const {fn , params } = props;
        fn(params);
    } else {
        const { fn } = props;
        fn();
    }
    return <div/>;
}

假设我们有两个函数,一个不带参数,另一个带参数:

declare const getPost1: () => Promise<ResponsePost>;
declare const getPost2: (id: string) => Promise<ResponsePost>;

...下面是使用这些组件的示例:

// Works, there are no `params` and `fn` doesn't expect them
const a = <RGBoundary fn={getPost1} />;
// Works, `params` is provided and `fn` expects them
const b = <RGBoundary fn={getPost2} params="x" />;
// Fails, because there is no `params` but `getPost` expects them
const c = <RGBoundary fn={getPost2} />;

Playground link

Typescript相关问答推荐

使用前的组件渲染状态更新

为什么在TypScript中写入typeof someArray[number]有效?

用泛型类型覆盖父类函数导致类型y中的Property x不能赋给基类型Parent中的相同属性."'''''' "

在Typescribe中,extends工作,但当指定派生给super时出错""

typescribe警告,explate—deps,useEffect依赖项列表

创建一个根据布尔参数返回类型的异步函数

了解类型规则中的关键字

如何使我的函数专门针对联合标记?

为什么不能使用$EVENT接收字符串数组?

如何使用Geojson模块和@Types/Geojson类型解析TypeScrip中的GeoJSON?

如何在react组件中使用doctype和html标签?

限制返回联合的TS函数的返回类型

为什么在leetcode问题的测试用例中,即使我确实得到了比预期更好的解决方案,这段代码也失败了?

使用TypeScrip的类型继承

正确使用相交类型的打字集

我不明白使用打字脚本在模板中展开参考

TypeScrip:使用Cypress测试包含插槽的Vue3组件

Vite+Chrome扩展 list v3-;不能在模块外使用import语句;对于inpage脚本

如何按成员资格排除或 Select 元组?

在Typescript 无法正常工作的 Three.js 中更新动画中的 GLSL 统一变量