在TypeScript的Next.js中使用Auth创建HOC的最佳方法是什么?

disho6za  于 2023-10-18  发布在  TypeScript
关注(0)|答案(2)|浏览(118)

我有一个Next.js应用程序,我使用next-auth包。我试图创建一个HOC,它将围绕实际组件,并将确定它是否有会话。我也在使用ESLINT。下面是我的代码:

import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';

type Props = any;

const withAuth = (Component: React.ComponentType<Props>) => {
  const Auth = (props: Props) => {
    const router = useRouter();
    const { status } = useSession({
      required: true,
      onUnauthenticated() {
        router.push('/welcome/login');
      },
    });

    if (status === 'loading') {
      return 'Loading ...';
    }

    return <Component {...props} />;
  };
  return Auth;
};

export default withAuth;

Eslint给了我一个关于我使用any类型的警告。我试着把这两行改为我使用泛型类型的地方:

const withAuth = <P extends {}>(Component: React.ComponentType<P>) => {
  const Auth = (props: P) => {

但现在它给了我一个错误:

Error: Don't use `{}` as a type. `{}` actually means "any non-nullish value".
- If you want a type meaning "any object", you probably want `object` instead.
- If you want a type meaning "any value", you probably want `unknown` instead.
- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.
- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead.  @typescript-eslint/ban-types

当我们必须将组件作为props传递时,编写HOC的最佳方法是什么?我不知道它会是什么样的组件,

uz75evzq

uz75evzq1#

一般来说,TypeScript建议不要使用{}作为泛型类型约束,因为它不施加任何类型检查约束,所以它本质上和使用any一样宽松。
您可以使用unknownRecord<string, unknown>来获得更好的类型安全性,并且不会弹出ESLint错误。
这些类型基本上假设您不知道该对象将采用什么形状,但它不会是nullundefined,使其足够灵活,可以 Package 任何组件。
在你的例子中:

const withAuth = <P extends Record<string, unknown>>(
  Component: React.ComponentType<P>
): React.FC<P> => {
  const Auth: React.FC<P> = (props) => {
    const router = useRouter();
    const { status } = useSession({
      required: true,
      onUnauthenticated() {
        router.push('/welcome/login');
      },
    });

    if (status === 'loading') {
      return 'Loading ...';
    }

    return <Component {...props} />;
  };

  return Auth;
};

export default withAuth;

所以这里,props参数的类型不是any,而是P,这是我们限制为Record<string, unknown>的泛型类型。

c3frrgcw

c3frrgcw2#

要使用TypeScript在Next.js中创建具有身份验证的高阶组件(HOC),您可以为组件props定义一个泛型类型,并在整个代码中使用该类型。以下是如何重写withAuth HOC的示例:

import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import { ComponentType, ReactElement } from 'react';

type AuthProps = {
  // Define any additional props that the authenticated component may need here.
};

type WithAuthProps = {
  // Define the common props shared by all components wrapped by withAuth.
};

// Define the withAuth HOC
const withAuth =
  <P extends WithAuthProps>(
    WrappedComponent: ComponentType<P>
  ): ComponentType<P> =>
  (props: P): ReactElement => {
    const router = useRouter();
    const { status } = useSession({
      required: true,
      onUnauthenticated() {
        router.push('/welcome/login');
      },
    });

    if (status === 'loading') {
      return <div>Loading ...</div>;
    }

    // Pass any additional props required by the wrapped component
    // to ensure type safety.
    const authProps: AuthProps = {
      // Define your authentication-related props here if needed.
    };

    return <WrappedComponent {...props} {...authProps} />;
  };

export default withAuth;

相关问题