类型'(props:ITableProps)=> JSX.Element'的参数不能分配给类型...的参数-React HOC

时间:2020-07-09 11:48:49

标签: javascript reactjs typescript react-hoc

我有一个装载机HOC

HOC:

const withLoader = <P extends object>(WrappedComponent: new () => React.Component<P, any>, loading: boolean) => {

    return class WithLoading extends React.Component<P, any> {
        render() {

            return (
                <div >
                    <div className={`${loading} ? 'loader' : '' "></div>
                    <WrappedComponent {...this.props} /> 
                </div>
            )
        }
    }
}

我正以这种方式使用它,例如:

const TableHOC = withLoader(Table,true);

例如,现在我的表或任何其他组件将具有其自己定义良好的props接口。一切都很好键入。

但是我遇到了这个问题

Argument of type '(props: ITableProps) => JSX.Element' is not assignable to parameter of type 'new () => Component<object, any, any>'.
  Type '(props: ITableProps) => Element' provides no match for the signature 'new (): Component<object, any, any>'.ts(2345)

我该如何解决?

1 个答案:

答案 0 :(得分:1)

您将改为使用React.ComponentType作为类型:

const withLoader = <P extends object>(WrappedComponent: React.ComponentType<P>, loading: boolean) => {
  // ...
}

不过,请注意,如果您打算通过状态更改来切换loading的值,则需要将其作为道具传递。这是因为每次调用withLoader来获取增强组件时,它都是一个新组件,这意味着,如果在render中进行操作,React将始终卸载并重新安装该渲染组件。这也意味着增强组件内部的任何状态都将丢失。

例如:

interface WithLoadingProps {
  loading: boolean;
}

const withLoader = <P extends object>(
  WrappedComponent: React.ComponentType<P>
) => {
  return class WithLoading extends React.Component<P & WithLoadingProps, any> {
    render() {
      const { loading } = this.props;
      return (
        <div>
          <div className={loading ? "loader" : ""}>
            <WrappedComponent {...this.props} />
          </div>
        </div>
      );
    }
  };
};

样品使用:

const MyComponent = ({ text }: { text: string }) => {
  return <div>{text}</div>;
};
const MyLoadingComponent = withLoader(MyComponent);

class Foo extends React.Component<{}, { loading: boolean }> {
  render() {
    const { loading } = this.state;
    return <MyLoadingComponent loading={loading} text="foo" />;
  }
}

首先,考虑添加displayName as instructed in React's documentation-使用React的devtools时,这将增强您的调试体验。

使用:

enter image description here

没有:

enter image description here

interface WithLoadingProps {
  loading: boolean;
}

const getDisplayName = <P extends object>(Component: React.ComponentType<P>) =>
  Component.displayName || Component.name || "Component";

const withLoader = <P extends object>(WrappedComponent: React.ComponentType<P>) => {
  class WithLoading extends React.Component<P & WithLoadingProps, any> {
    static readonly displayName = `WithLoading(${getDisplayName(WrappedComponent)})`;

    render() {
      const { loading } = this.props;
      return (
        <div>
          <div className={loading ? "loader" : ""}>
            <WrappedComponent {...this.props} />
          </div>
        </div>
      );
    }
  }

  return WithLoading;
};