'(props: ITableProps) => JSX.Element' 类型的参数不可分配给类型的参数 ... - React HOC
Argument of type '(props: ITableProps) => JSX.Element' is not assignable to parameter of type ... - 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);
现在我的 table 或任何其他组件,例如,将有自己明确定义的道具界面。一切都打得很好。
但是我遇到了这个问题
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)
我该如何解决这个问题?
您需要使用 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 的开发工具时的调试体验。
与:
没有:
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;
};
我有一个装载机 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);
现在我的 table 或任何其他组件,例如,将有自己明确定义的道具界面。一切都打得很好。
但是我遇到了这个问题
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)
我该如何解决这个问题?
您需要使用 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 的开发工具时的调试体验。
与:
没有:
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;
};