在Typescript中处理高阶组件中的道具

时间:2018-08-13 12:01:12

标签: reactjs typescript

我在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;

1 个答案:

答案 0 :(得分:1)

您需要向HOC添加一些通用的技巧,以便将prop类型转发到包装的组件。此外,包装的组件道具需要具有字段handleChangehandleSubmit,而生成的组件需要将这些字段排除在外(因为它们是由HOC提供的)。为了使它起作用,我们可以使用Exclude仅获取不是handleChangehandleSubmit的键,并使用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" />