首页 > 解决方案 > IFormContext 只引用了一个类型,但在这里用作值

问题描述

我正在尝试为离子反应形式建立验证。在我这样做之前,我需要获取输入的状态值。我有一个字段组件,它描述了字段、一个表单结构组件和需要上述两个组件的表单页面。以下是我的表单字段代码:

import React, {FormEvent} from "react";
import { IErrors } from "./ResetPassword";
import { IonInput} from "@ionic/react";

type Editor = "textbox";

export interface IFieldProps {
    id: string;
    name: string;
    label?: string;
    editor?: Editor;
    onIonChange?: any;
    value?: any;
    ionChangeValue?: string;
}

export const ResetField: React.FunctionComponent<IFieldProps> = ({
  id,
  name,
  label,
  editor,
  value,
  onIonChange
})=>{
    return (
        <div className="form-group">
            {label && <label htmlFor={id}>{label}</label>}
            {editor!.toLocaleLowerCase()=== "textbox" && (
                <IonInput
                  id={id}
                  name={name}
                  type="password"
                  value={value}
                  onIonChange={onIonChange}
                  onBlur={()=>
                      (e: FormEvent<HTMLIonInputElement>)=> 
                          console.log(e)
                  }
                  className="form-control"
                  />
            )}
        </div>
    )
};

ResetField.defaultProps = {
    editor: "textbox"
};

下面是表单结构的代码:

import * as React from "react";
import { IonPage, IonHeader, IonInput, IonItem, IonContent, IonLabel, IonToolbar, IonTitle, IonButton } from "@ionic/react";
import '../css/app.scss';
import { ResetField } from "./resetFormFields";



interface IFormProps {
    render: () => React.ReactNode;
}

export interface IFormContext extends IFormState {
    /* Function that allows values in the values state to be set */
    setValues: (values: IValues) => void;
  }
  /*
   * The context which allows state and functions to be shared with Field.
   * Note that we need to pass createContext a default value which is why undefined is unioned in the type
   */
  export const FormContext =
    (React.createContext < IFormContext) | (undefined > undefined); //<--- I am getting an error saying 'IFormContext' only refers to a type, but is used as a value here



export interface IValues {
    [key: string]: any;
}

export interface IErrors {
    [key: string]: string;
}

export interface IFormState {
    values: IValues;
    errors: IErrors;
    submitSuccess?: boolean;
}

export interface IFormContext extends IFormState {
    
    setValues: (values: IValues) => void;
  }

export class Reset extends React.Component<IFormProps, IFormState> {

    
  constructor(props: IFormProps) {
      super(props);

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

  private haveErrors(errors: IErrors) {
    let haveError: boolean = false;
    Object.keys(errors).map((key: string)=> {
        if(errors[key].length > 0){
            haveError = true;
        }
    });
    return haveError;
}

 private handleSubmit = async (
     e: React.FormEvent<HTMLFormElement>): Promise<void> => {
         e.preventDefault();
         
         if(this.validateForm()){
             const submitSuccess: boolean = await this.submitForm();
             this.setState({submitSuccess});
         }

         console.log(this.state.values);
     }

    private validateForm(): boolean {
        return true;
    }

    private async submitForm(): Promise<boolean> {
        return true;
    }

    public render() {

        const { submitSuccess, errors } = this.state;
        return (
            <IonPage id="login-registration-page">
            <IonHeader>
              <IonToolbar color="primary">
                <IonTitle>Reset Password</IonTitle>
              </IonToolbar>
            </IonHeader>
            <IonContent>
            <form onSubmit={this.handleSubmit} className="login-registration-form ion-padding" noValidate={true}>
              
                <div className="container">
                    {this.props.render()}
                    <div className="form-group">
                        <IonButton
                           type="submit"
                           disabled={this.haveErrors(errors)}
                           expand="block"
                           >Submit</IonButton>
                    </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 occured
                            </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>
            </IonContent>
            </IonPage>
        )
    }
}

以下是我的 resetForm 页面代码:

import React, {useState} from "react";
import { Reset } from "../components/ResetPassword";
import { ResetField } from "../components/resetFormFields";
import { RouteComponentProps } from 'react-router-dom';
import { IonInput} from "@ionic/react";
import '../css/app.scss';

interface OwnProps extends RouteComponentProps {}

interface ResetProps extends OwnProps {};


export const ResetForm: React.FunctionComponent<ResetProps> = () => {
    const [inputCurrentPassword, setCurrentPassword] = useState('');
        const [inputNewPawword, setNewPassword] = useState('');
        const [inputConfirmPassword, setConfirmPassword] = useState('');
    return (
    <Reset
          render={()=> (
              <React.Fragment>
                  <div className="alert alert-success" role="alert">
                      Reset your password to activate your account
                  </div>
                  <ResetField id="currentPassword" name="currentPassword" label="Current Password:" value={inputCurrentPassword} onIonChange={(e: { detail: { value: any; }; }) => setCurrentPassword(e.detail.value!)}/>
                  <ResetField id="newPassword" name="newPassword" label="New Password:" value={inputNewPawword} ionChangeValue="setNewPassword" onIonChange={(e: { detail: { value: any; }; }) => setNewPassword(e.detail.value!)}/>
                  <ResetField id="retypePassword" name="retypePassword" label="Confirm Password:" value={inputConfirmPassword} ionChangeValue="setConfirmPassword" onIonChange={(e: { detail: { value: any; }; }) => setConfirmPassword(e.detail.value!)}/>
              </React.Fragment>
          )}
          />
   )
   
}

在表单结构代码中,我收到错误消息'IFormContext' only refers to a type, but is used as a value here。我不明白这里的问题。我明白了,因为 IFormContext 是一个接口,所以它在这里是一种类型。如果是一堂课,我不会有问题。但这里需要是一个接口。

标签: javascriptreactjstypescriptionic-react

解决方案


您的错误是由于括号放错了。与类型、接口和类无关,这一切都很好。

export const FormContext = (React.createContext < IFormContext) | (undefined > undefined); 

需要固定到

export const FormContext = React.createContext<IFormContext | undefined>(undefined); 

推荐阅读