关于在HoC中省略道具有一个不寻常的问题
我有反应成分:
interface IMyComponentProps {
prop1: string,
prop2: Function,
items1: string[],
items2: string[],
}
我有HOC,它接受了这个组件并将item1和items2传递给它
interface IWithItems {
items1: string[],
items2: string[],
}
type WithoutItems<T extends IWithItems> = Omit<T, 'items1'|'items2'>;
function HoC<T extends IWithItems>(
WrappedComponent:
React.ComponentClass<T>
| React.FunctionComponent<T>,
): React.ComponentClass<WithoutItems<T>> {
class WithItemsWrapper extends React.Component<WithoutItems<T>, IWithItems> {
state = {
items1: [],
items2: [],
};
async componentDidMount() {
const items1 = await this.getItems1();
const items2 = await this.getItems2();
this.setState({
items1,
items2,
});
}
getItems1 = () => (
// from backend
);
getItems2 = () => (
// from backend
);
render() {
return (
<WrappedComponent
{...this.props}
items1={this.state.items1}
items2={this.state.items2}
/>
);
}
}
return hoistNonReactStatics(WithItemsWrapper, WrappedComponent);
}
包装的组件具有自己的道具,这些道具包含item1,item2。 HoC从后端提取项目并将其传递给包装的组件
在我的index.ts
文件中,我将其导出为
export default HoC(MyComponent);
想法是,在此导出并导入到其他文件MyComponent
中之后,应该需要prop1和prop2,但不需要item1和item2,因为它们已经在HoC中通过了。
但是现在它说
Error:(59, 12) TS2322: Type 'Readonly<Pick<T, Exclude<keyof T, "items1" | "items2">>> & { items1: never[]; items2: never[]; children?: ReactNode; }' is not assignable to type 'IntrinsicAttributes & T & { children?: ReactNode; }'.
Type 'Readonly<Pick<T, Exclude<keyof T, "items1" | "items2">>> & { items1: never[]; items2: never[]; children?: ReactNode; }' is not assignable to type 'T'.
是否可能,如果可以-我在做什么错了?
答案 0 :(得分:0)
您采取相反的方式。 HoC
接受包含items1
和items2
的组件,并返回不包含items1
和items2
的HOC。所以对于组件
let ResultingComponent = HoC(MyComponent);
您应仅提供prop1
和prop2
。 items1
和items2
将由HoC填充。
如果您希望传递不包含items1
和items2
的组件,但生成的组件包含items1
和items2
,则应该这样做
function HoC<T>(
WrappedComponent:
React.ComponentClass<T>
| React.FunctionComponent<T>,
): React.ComponentClass<T & IWithItems> {
class WithItemsWrapper extends React.Component<T & IWithItems, IWithItems> {
render() {
return (
<>
// Do some rendering based on this.props.items1 and this.props.items2
<div>{this.props.items1.map(e => (<div>{e}</div>))}</div>
<WrappedComponent
{...this.props}
/>
</>
);
}
}
return hoistNonReactStatics(WithItemsWrapper, WrappedComponent);
}
但是请注意,在这种情况下,应将item1
和item2
提供给HoC的结果组件。在HoC内部,您不应该从后端接收这些道具,但是您应该基于这些道具进行渲染,并且不要将其传递给WrappedComponent
。
答案 1 :(得分:0)
我想我找到了解决方法
首先简化WithoutItems并更改HOC定义
import { pipeOne } from './pipeone.pipe';
const transformedItems = new pipeOne().transform(this.items);
接下来的事情是使道具地图显式输入P
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
type Diff<T, K> = Omit<T, keyof K>;
type WithoutItems<T> = Diff<T, IWithItems>;
function HoC<P>(
WrappedComponent:
React.ComponentClass<P>
| React.FunctionComponent<P>,
): React.ComponentClass<WithoutItems<P>> {
class WithItemsWrapper extends React.Component<WithoutItems<P>, IWithItems> {
所有其他事物保持不变。
解决方案已建立here