我在Login组件中传递道具,该组件包装在另一个使用TypeScript在React中传递道具的组件“ FormHandle”中。但是在Login组件中会引发以下错误:
[ts] `Property 'loginLabel' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<(Anonymous class)> & Readonly<{ children?: ReactNo...'.`
LoginForm中道具的界面是:-
interface ILoginformProps {
//below props coming from login component
loginLabel: string;
passwordLabel: string;
// below props coming from form handler Heigher order component
handleChange: () => void;
handleSubmit: () => void;
}
现在,当我将LoginForm称为:-
<LoginForm loginLabel="Login" passwordLabel="password"/>
出现上述错误。
包装代码是:-
import * as React from "react";
// This higher order component wraps FORM functionality
function HandleForm(Form: any, callAction: (state: object) => void) {
return class extends React.Component<object, {}>{
constructor(props: any) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {};
}
handleChange(e: any) {
const { value, name } = e.target;
this.setState({ [name]: value });
}
handleSubmit(e: any) {
e.preventDefault();
let state = this.state;
callAction(state);
}
render() {
return <Form {...this.props} handleChange={this.handleChange} handleSubmit={this.handleSubmit} />;
}
};
}
export default HandleForm;
答案 0 :(得分:1)
您需要向HOC添加一些通用的技巧,以便将prop类型转发到包装的组件。此外,包装的组件道具需要具有字段handleChange
和handleSubmit
,而生成的组件需要将这些字段排除在外(因为它们是由HOC提供的)。为了使它起作用,我们可以使用Exclude
仅获取不是handleChange
和handleSubmit
的键,并使用Pick
从原始道具中提取它们:
import * as React from 'react';
interface HandleFormProps {
handleChange: (e: any) => void;
handleSubmit: (e: any) => void;
}
// This higher order component wraps FORM functionality
// TProp will be the props of the passed in component
function HandleForm<TProp extends HandleFormProps>(Form: React.ComponentType<TProp>, callAction: (state: object) => void) {
// We return a component that pick only the properties that are not provided by the HOC
return class extends React.Component<Pick<TProp, Exclude<keyof TProp, keyof HandleFormProps>>, {}>{
constructor(props: any) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {};
}
handleChange(e: any) {
const { value, name } = e.target;
this.setState({ [name]: value });
}
handleSubmit(e: any) {
e.preventDefault();
let state = this.state;
callAction(state);
}
render() {
return <Form {...this.props} handleChange={this.handleChange} handleSubmit={this.handleSubmit} />;
}
};
}
// Usage
interface ILoginformProps {
//below props coming from login component
loginLabel: string;
passwordLabel: string;
// below props coming from form handler Heigher order component
handleChange: () => void;
handleSubmit: () => void;
}
// Sample component, add your own implementation
class LoginComponent extends React.Component<ILoginformProps> {
}
const LoginForm = HandleForm(LoginComponent, () => { });
let d = <LoginForm loginLabel="Login" passwordLabel="password" />