如何使用TypeScript实现高阶组件?

问题描述 投票:0回答:1

我正在尝试在 TypeScript 中实现一个高阶组件,以便我可以将 ErrorBoundary 作为参数传递给高阶组件,然后高阶组件返回用户的当前位置,以便我可以在我的 ErrorBoundary 组件中使用它.

错误边界:

import React from "react";

interface ErrorBoundaryProps {
  fallback: React.ReactNode;
  children: React.ReactNode;
  location: {
    pathname: string;
  };
}

class ErrorBoundary extends React.Component<ErrorBoundaryProps> {
  state = { hasError: false };

  static getDerivedStateFromError(error: Error) {
    return { hasError: true };
  }

  componentDidUpdate(previousProps: ErrorBoundaryProps) {
    if (previousProps.location.pathname !== this.props.location.pathname) {
      this.setState({ hasError: false });
    }
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback;
    }
    return this.props.children;
  }
}

export default ErrorBoundary;

WithRouter(高阶组件):

import { useLocation } from "react-router-dom";

function WithRouter(OriginalComponent: React.ComponentType) {
  const NewComponent = (props: any) => {
    const location = useLocation();

    return <OriginalComponent {...props} location={location} />;
  };
  return NewComponent;
}

显然 TypeScript 编译器不满意,我不知道如何修复它。抱歉,我对此很陌生!

我刚刚尝试过不同的实现,但似乎没有任何效果。

如果这有帮助,这就是 JavaScript 中的工作原理:

import { useLocation } from "react-router-dom";

function WithRouter(OriginalComponent) {
  const NewComponent = (props) => {
    const location = useLocation();

    return <OriginalComponent location={location} {...props} />;
  };
  return NewComponent;
}

但我只是在努力将其转换为 TypeScript。

error-handling react-router higher-order-components
1个回答
0
投票

我在代码中看到的唯一明显的问题是

React.ComponentType
需要一个参数。

示例:

function withRouter<P extends {}>(Component: React.ComponentType<P>) {
  const NewComponent = (props: any) => {
    const location = useLocation();

    return <Component {...props} location={location} />;
  };
  return NewComponent;
}

const withRouter = <P extends {}>(Component: React.ComponentType<P>) => (
  props: any
) => {
  const location = useLocation();

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

用途:

const ErrorBoundaryWithRouter = withRouter(ErrorBoundary);

您可能还应该使用从 React-Router-DOM 导出的

Location
类型作为
ErrorBoundaryProps
接口。

import type { Location } from "react-router-dom";

interface ErrorBoundaryProps {
  fallback: React.ReactNode;
  children: React.ReactNode;
  location: Location;
}

或者更准确地说,将

WithRouterProps
定义为单独的接口,并将其扩展为
ErrorBoundaryProps
接口:

import type { Location } from "react-router-dom";

interface WithRouterProps {
  location: Location;
}

interface ErrorBoundaryProps extends WithRouterProps {
  fallback: React.ReactNode;
  children: React.ReactNode;
}

const withRouter = <P extends object>(Component: React.ComponentType<P>) => (
  props: Omit<P, keyof WithRouterProps>
) => {
  const location = useLocation();

  return <Component {...props as P} location={location} />;
};
© www.soinside.com 2019 - 2024. All rights reserved.