Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs 在接口和类中多次指定相同声明的概念是什么?_Reactjs_Typescript - Fatal编程技术网

Reactjs 在接口和类中多次指定相同声明的概念是什么?

Reactjs 在接口和类中多次指定相同声明的概念是什么?,reactjs,typescript,Reactjs,Typescript,我正在努力学习用typescript处理表单,并从中做出反应。第一次做出明确的反应 下面是Form.tsx import * as React from "react"; interface IFormProps { /* The http path that the form will be posted to */ action: string; } export interface IValues { /* Key value pairs for all the field

我正在努力学习用typescript处理表单,并从中做出反应。第一次做出明确的反应

下面是
Form.tsx

import * as React from "react";

interface IFormProps {
  /* The http path that the form will be posted to */
  action: string;
}

export interface IValues {
  /* Key value pairs for all the field values with key being the field name */
  [key: string]: any;
}

export interface IErrors {
  /* The validation error messages for each field (key is the field name */
  [key: string]: string;
}

export interface IFormState {
  /* The field values */
  values: IValues;

  /* The field validation error messages */
  errors: IErrors;

  /* Whether the form has been successfully submitted */
  submitSuccess?: boolean;
}

export class Form extends React.Component<IFormProps, IFormState> {
  constructor(props: IFormProps) {
    super(props);

    const errors: IErrors = {};
    const values: IValues = {};
    this.state = {
      errors,
      values
    };
  }

  /**
   * Returns whether there are any errors in the errors object that is passed in
   * @param {IErrors} errors - The field errors
   */
  private haveErrors(errors: IErrors) {
    let haveError: boolean = false;
    Object.keys(errors).map((key: string) => {
      if (errors[key].length > 0) {
        haveError = true;
      }
    });
    return haveError;
  }

  /**
   * Handles form submission
   * @param {React.FormEvent<HTMLFormElement>} e - The form event
   */
  private handleSubmit = async (
    e: React.FormEvent<HTMLFormElement>
  ): Promise<void> => {
    e.preventDefault();

    if (this.validateForm()) {
      const submitSuccess: boolean = await this.submitForm();
      this.setState({ submitSuccess });
    }
  };

  /**
   * Executes the validation rules for all the fields on the form and sets the error state
   * @returns {boolean} - Whether the form is valid or not
   */
  private validateForm(): boolean {
    // TODO - validate form
    return true;
  }

  /**
   * Submits the form to the http api
   * @returns {boolean} - Whether the form submission was successful or not
   */
  private async submitForm(): Promise<boolean> {
    // TODO - submit the form
    return true;
  }

  public render() {
    const { submitSuccess, errors } = this.state;
    return (
      <form onSubmit={this.handleSubmit} noValidate={true}>
        <div className="container">
          {/* TODO - render fields */}
          <div className="form-group">
            <button
              type="submit"
              className="btn btn-primary"
              disabled={this.haveErrors(errors)}
            >
              Submit
            </button>
          </div>
          {submitSuccess && (
            <div className="alert alert-info" role="alert">
              The form was successfully submitted!
            </div>
          )}
          {submitSuccess === false &&
            !this.haveErrors(errors) && (
              <div className="alert alert-danger" role="alert">
                Sorry, an unexpected error has occurred
              </div>
            )}
          {submitSuccess === false &&
            this.haveErrors(errors) && (
              <div className="alert alert-danger" role="alert">
                Sorry, the form is invalid. Please review, adjust and try again
              </div>
            )}
        </div>
      </form>
    );
  }
}
import*as React from“React”;
界面道具{
/*表单将发布到的http路径*/
动作:字符串;
}
导出接口IValues{
/*键为字段名的所有字段值的键值对*/
[键:字符串]:任意;
}
导出接口错误{
/*每个字段的验证错误消息(键是字段名*/
[键:字符串]:字符串;
}
导出接口状态{
/*字段值*/
价值观:价值观;
/*字段验证错误消息*/
错误:错误;
/*表单是否已成功提交*/
submitSuccess?:布尔值;
}
导出类表单扩展了React.Component{
构造器(道具:道具){
超级(道具);
常量错误:IErrors={};
常量值:IValues={};
此.state={
错误,
价值观
};
}
/**
*返回传入的errors对象中是否存在任何错误
*@param{IErrors}errors-字段错误
*/
私有haveErrors(错误:IErrors){
设haveError:boolean=false;
Object.keys(errors).map((key:string)=>{
如果(错误[key]。长度>0){
haveError=true;
}
});
返回错误;
}
/**
*处理表格提交
*@param{React.FormEvent}e-表单事件
*/
私有handleSubmit=async(
e:React.FormEvent
):承诺=>{
e、 预防默认值();
if(this.validateForm()){
const submitSuccess:boolean=wait this.submitForm();
this.setState({submitSuccess});
}
};
/**
*执行表单上所有字段的验证规则并设置错误状态
*@返回{boolean}-表单是否有效
*/
私有validateForm():布尔值{
//TODO-验证表单
返回true;
}
/**
*将表单提交到http api
*@returns{boolean}-表单提交是否成功
*/
专用异步submitForm():承诺{
//待办事项-提交表格
返回true;
}
公共渲染(){
const{submitSuccess,errors}=this.state;
返回(
{/*TODO-呈现字段*/}
提交
{提交成功&&(
表单已成功提交!
)}
{submitSuccess===false&&
!this.haveErrors(errors)&(
很抱歉,发生了意外错误
)}
{submitSuccess===false&&
这个.有错误(errors),(
抱歉,表单无效。请检查、调整并重试
)}
);
}
}
我不理解的是,类
表单的
构造函数
具有

  • 错误
它们都可以作为简单的对象数组来处理,但为什么会有这么多声明呢?正如我所看到的:

  • IValues
  • IErrors
代表他们


我寻求帮助来理解所有这些额外声明背后的概念。

当您写入接口时,您就同意了一个契约:接口的形式在编译时保证是数据的形式

当你传递裸数据结构时,你没有这样的保证:你得到的数据可能比你想象的要多或少,唯一的验证方法是运行时检查。这些检查比编译时检查更昂贵

它们都可以作为简单的对象数组来处理

处理事情的方法不止一种,而这篇文章的作者已经决定用下面的方法来处理事情。这是否是处理事情的最佳方法取决于你自己。我只能解释它们背后的原因

export interface IValues {
  /* Key value pairs for all the field values with key being the field name */
  [key: string]: any;
}

export interface IErrors {
  /* The validation error messages for each field (key is the field name */
  [key: string]: string;
}
第一个接口(
IValues
)声明了一个契约,其中任何实现它的对象都必须包含与任何类型的值耦合的字符串键

第二个接口(
IErrors
)指定一个协定,其中任何实现它的对象都必须包含指向字符串值的字符串键

这是键值对的概念,也称为哈希、字典或映射,具体取决于您所熟悉的语言

Typescript实际上有一个名为
Record
的内置类型,它允许您执行上述操作,而不会过于冗长

type Record<K extends keyof any, T> = { [P in K]: T }
当遇到第一个错误时,此检查可以短路以返回true。顺便说一句,它只检查至少一个单数形式的错误,因此最好将其命名为
hasrerror
hasrerrors

  private hasError(errors: IErrors) {
    for (let [key, value] of Object.entries(errors))
     if (value)  // <---- if (value) alone is enough as an empty string '' is falsy
       return true;

   return false;
  }
为什么?
submitSuccess
定义为布尔值,无需将其设置为false


谢谢你,但我无法联系。你能给我举个例子吗?这样我就可以连接我的神经网络了……对不起,我的无知:(它们都可以作为简单的对象数组来处理:当然,但是您可能会遇到运行时错误或奇怪的行为,因为代码期望它们是对象,而不是数组。指定类型正好可以避免此类错误:如果您尝试使用数组初始化它们,则会出现编译时错误。如果商店只接受Visa卡,如果他们在支付页面上清楚地告诉你这一点,对你来说更容易,而不是让你尝试使用万事达卡并得到难以诊断的错误。这里也一样:界面避免出错。我相信
界面
更为人所知
  private haveErrors(errors: IErrors) {
    let haveError: boolean = false;
    Object.keys(errors).map((key: string) => {
      if (errors[key].length > 0) {
        haveError = true;
      }
    });
    return haveError;
  }
  private hasError(errors: IErrors) {
    for (let [key, value] of Object.entries(errors))
     if (value)  // <---- if (value) alone is enough as an empty string '' is falsy
       return true;

   return false;
  }
{submitSuccess === false && ...} = {!submitSuccess && ...}