-1

请查看elfe-if以下代码中条件内的验证方法。我无法useLocation调用react-router-dom. 我在网上看到过问题,其中一个类似这样: Invalid hook call。但解决方案建议从类更改为函数。它可能不是我的解决方案,因为我在表单验证期间使用我的类的实例来查找值。

export class Reset extends React.Component<IFormProps, IFormState> {
private currentPasswordProvided: boolean;
private passwordValidated: boolean;
private completeValidation: boolean;
private resetParams: ResetPassword;
    
  constructor(props: IFormProps) {
      super(props);

      const errors: IErrors = {};
      const values: IValues = {};
      this.state = {
          errors,
          values
      };
      this.currentPasswordProvided=false;
      this.passwordValidated= false;
      this.completeValidation=false;
      this.resetParams = {
          adminID : '',
          currentPassword: '',
          newPassword: '',
      }
  }

 private setValues = (values: IValues)=>{
     this.setState({values: {...this.state.values, ...values}})
    
 };

 private validate = (fieldName: string, value: string): string => {
     let newError: string = "";
     if(fieldName!=='retypePassword'){
         
        if (
            this.props.fields[fieldName] &&
            this.props.fields[fieldName].validation
        ){
            newError = this.props.fields[fieldName].validation!.rule(
                value,
                fieldName,
                this.props.fields[fieldName].validation!.args
            );
            if(fieldName=='currentPassword' && newError === "")
            {
                this.currentPasswordProvided = true;
            }
            else if(fieldName=='newPassword' && newError === "")
            {
                this.passwordValidated = true;
            }
        }
     }
     else if(fieldName === 'retypePassword'){
        if (
            this.props.fields[fieldName] &&
            this.props.fields[fieldName].ComparePasswordValidation
        ){
            let passwordValues : CompareValue = {
                newPassword: this.state.values.newPassword
            }
            newError = this.props.fields[fieldName].ComparePasswordValidation!.rule(
                value,
                passwordValues,
                this.props.fields[fieldName].ComparePasswordValidation!.args
            );
            if(this.currentPasswordProvided===true&&this.passwordValidated===true&&newError===""){
                const params = useLocation();  //<------ unable to call this  ------------
                const adminID = params.pathname.substr(params.pathname.lastIndexOf('/')+1);
                this.resetParams = {
                    adminID: adminID,
                    currentPassword: this.state.values.currentPassword,
                    newPassword: this.state.values.newPassword,
                }
                this.completeValidation = true;
            }
            else{
                this.completeValidation = false;
            }
        }
     }
     this.state.errors[fieldName] = newError;
     this.setState({
         errors: { ...this.state.errors, [fieldName]: newError}
     });
     return newError;
 }

  private haveErrors(errors: IErrors) {
    let haveError: boolean = true;
    Object.keys(errors).map((key: string)=> {

        if(errors[key].length > 0){
            haveError = true;
        }
    });
    return haveError;
}

 private async handleSubmit (
    e: React.FormEvent<HTMLFormElement>
  ): Promise<void> {
       e.preventDefault();
        try {
            
            console.log(`These are the values----> ${this.state.values}`)
            const resetParams : ResetPassword = {
                adminID: 'adminID',
                currentPassword : this.state.values.currentPassword,
                newPassword: this.state.values.newPassword,
            }
    
            console.log(`These are the params being sent to the API ----> ${JSON.stringify(resetParams)}`)
            /* 
                API call code goes here
            */
          } catch (e) {
            console.log(`Request failed: ${e}`);
            // setShowAlert(true);
          }
     }

    public render() {
        const { submitSuccess, errors } = this.state;
        const context: IFormContext = {
            ...this.state,
            setValues: this.setValues,
            validate: this.validate
        };
        // console.log(`This is the state ----> ${JSON.stringify(this.state.values)}`)
        return (
            <IonPage id="login-registration-page">
            <IonHeader>
              <IonToolbar color="primary">
                <IonTitle>Reset Password</IonTitle>
              </IonToolbar>
            </IonHeader>
            <IonContent>
                <FormContext.Provider value={context}>
            <form onSubmit={this.handleSubmit} className="login-registration-form ion-padding">
                <div className="container">
                    {this.props.render()}
                    <div className="form-group">
                        <IonButton
                           type="submit"
                           //onClick={this.handleSubmit}
                           disabled={!this.completeValidation}
                           expand="block"
                           >Submit</IonButton>
                    </div>
                    {this.completeValidation === false && 
                          !this.haveErrors(errors) && (
                              <div className="alert alert-danger" role="alert">
                                  Sorry, an unexpected error has occured
                            </div>
                    )}
                </div>
            </form>
            </FormContext.Provider>
            </IonContent>
            </IonPage>
        )
    }
}

4

2 回答 2

1

useLocation是一个自定义反应钩子,只能在函数组件内部使用,即定义为 javascript 函数的组件。您的组件是一个类组件。

location在类组件中访问路由器上下文提供的对象,您可以使用withRouterHOC:

import React from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router";

// A simple component that shows the pathname of the current location
class ShowTheLocation extends React.Component {
  static propTypes = {
    match: PropTypes.object.isRequired,
    location: PropTypes.object.isRequired,
    history: PropTypes.object.isRequired
  };

  render() {
    const { match, location, history } = this.props;

    return <div>You are now at {location.pathname}</div>;
  }
}

// Create a new component that is "connected" (to borrow redux
// terminology) to the router.
const ShowTheLocationWithRouter = withRouter(ShowTheLocation);

HOC 将路由器上下文作为 props注入到您的组件中matchlocationhistory

于 2020-10-26T11:38:47.400 回答
0

类组件中不支持挂钩。如果您不能轻松地将其重写为功能组件,则一种选择是使用功能组件包装您的类组件并location作为道具传入。看起来你只是在使用,params.pathname所以你可以把它传入。

像这样的东西(组件名称只是一个建议):

  1. 重命名ResetResetBody
  2. 通过扩展为道具创建一个新类型。

interface IResetProps extends IFormProps {
    adminID : string;
}
  1. 创建一个名为的新组件Reset,如下所示:
function Reset(props : IFormProps){
    const params = useLocation();  //<------ unable to call this  ------------
    const adminID = params.pathname.substr(params.pathname.lastIndexOf('/')+1);

    return <ResetBody {...props} adminID={adminID} />
}
于 2020-10-26T11:51:31.963 回答