我将为您翻译如下内容,这是一篇关于IT技术的文章:
以下是我想要做的示例:
我尝试了几种变化,包括让P扩展ContainerProps,但似乎都不起作用。 我正在使用typescript 3.3.1版本。
我正试图在typescript中编写一个React高阶函数,它具有以下功能: (1)要求被包装的组件拥有特定的属性 (2)允许在包装器上设置被包装组件的属性 (3)具有特定于包装器的属性
我基本上已经使所有东西都运作了,但当我尝试在包装我的组件的匿名类上设置默认属性时,typescript会报错,而我无法解决。
我得到的错误信息是:
src/withContainer.tsx:33:3 - error TS2322: Type 'typeof (Anonymous class)' is not assignable to type 'ComponentClass<P & ContainerProps, any>'.
Types of property 'defaultProps' are incompatible.
Type '{ loading: Element; }' is not assignable to type 'Partial<P & ContainerProps>'.
33 return class extends React.Component<P & ContainerProps, ContainerState> {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34 // Why does typescript say this is an error?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
80 }
~~~~~
81 };
~~~~
以下是我想要做的示例:
这里是一个我想要实现的示例:
import * as React from "react";
/**
* Properties specific to the container component.
*/
export interface ContainerProps {
/* eslint-disable @typescript-eslint/no-explicit-any */
loading: React.ReactElement<any>;
}
export interface ContainerState {
data: {};
initialized: boolean;
}
/**
* Components being wrapped need a putData function on them.
*/
export interface PuttableProps {
/**
* Put data into state on the parent component.
*
* @param data Data to be put into state.
*/
putData(data: object): void;
}
/* eslint-disable max-lines-per-function */
export function withContainer<P>(
WrappedComponent: React.ComponentType<P & PuttableProps>
): React.ComponentClass<P & ContainerProps> {
return class extends React.Component<P & ContainerProps, ContainerState> {
// Why does typescript say this is an error?
static defaultProps = {
loading: <React.Fragment />
};
state: ContainerState = {
initialized: false,
data: {}
};
/**
* After mounting, simulate loading data and mark initialized.
*/
componentDidMount(): void {
// Simulate remote data load, 2 minutes after we mounted set initialized to true
setTimeout(() => {
this.setState({
initialized: true
});
}, 2000);
}
/**
* Set data as state on the parent component.
*/
private putData = (data: object): void => {
this.setState({ data });
};
/**
* Render the wrapped component.
*/
render(): React.ReactNode {
// If we haven't initialized the document yet, don't return the component
if (!this.state.initialized) {
return this.props.loading;
}
// Whatever props were passed from the parent, our data and our putData function
const props = {
...this.props,
...this.state.data,
putData: this.putData
};
return <WrappedComponent {...props} />;
}
};
}
export class ClickCounter extends React.Component<
PuttableProps & { count: number },
{}
> {
static defaultProps = {
count: 0
};
increment = () => {
this.props.putData({ count: this.props.count + 1 });
};
render(): React.ReactNode {
return (
<div>
<h1>{this.props.count}</h1>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
而它可以这样利用:
import React from "react";
import ReactDOM from "react-dom";
import { withContainer, ClickCounter } from "./withContainer";
const WrappedClickCounter = withContainer(ClickCounter);
const component = (
<WrappedClickCounter count={0} loading={<div>Loading...</div>} />
);
ReactDOM.render(component, document.getElementById("root"));
我尝试了几种变化,包括让P扩展ContainerProps,但似乎都不起作用。 我正在使用typescript 3.3.1版本。