我有一个装载机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)
我该如何解决?
答案 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时,这将增强您的调试体验。
使用:
没有:
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;
};