首页 > 解决方案 > react-hook useFormInput()表单验证不起作用

问题描述

链接到代码沙箱https://stackblitz.com/edit/react-cdv6mx?devtoolsheight=33&file=src/ResetPassword.js

解释: 当用户输入不正确的详细信息时,服务器会发送 400: bad request error 和一条消息,该消息可以在Response tab网络选项卡下看到。目的是在提交表单之前验证表单字段,并在输入不正确的字段时显示错误消息。此外,目的是禁用重置按钮,直到表单字段符合条件。因此,这将防止用户意外提交半输入的字段。

我有一个功能组件,其中有一个简单的形式。

问题:我正在调用validatForm()方法onChange。该方法应首先检查 newPassword 和 confirmPassword 是否相同,并且是否符合密码规则(要求),如果为真,则仅发送数据。

更新的代码在上面的 STACKBLITZ 链接中。

我使用useFormInput()如下

  const email = useFormInput("");
  const newPassword = useFormInput("");
  const confirmPassword = useFormInput("");

我写了一个useFormInput()方法

const useFormInput = (initialValue) => {
  const [value, setValue] = useState(initialValue);

  const handleChange = (e) => {
    setValue(e.target.value);
  };
  return {
    value,
    onChange: handleChange,
  };
};

和一个validateForm()方法,我把它传给我<button/>

/*  Your password must contain at least one capital letter, one
      *number and one lowercase letter, and it must contain at least 8
      *characters*/


const validateForm = (event) => {
    let pass = event.target.value;
    let reg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;
    let test = reg.test(pass);
    if (test) {
      this.setState({ value: event.target.value });
    } else {
      alert("password validation unsuccessful. Please try again.");
      return;
    }
  };

并在渲染()

<FormGroup row>
            <Label for="Email" sm={2}>
              Email
            </Label>
            <Col sm={4}>
              <Input
                type="email"
                name="email"
                id="Email"
                
                {...email}
              />
            </Col>
          </FormGroup>
          <FormGroup row>
            <Label for="newPassword" sm={2}>
              New Password
            </Label>
            <Col sm={4}>
              <Input
                type="password"
                name="password"
                id="newPassword"
                
                {...newPassword}
              />
            </Col>
          </FormGroup>
          <FormGroup row>
            <Label for="confirmPassword" sm={2}>
              Confirm Password
            </Label>
            <Col sm={4}>
              <Input
                type="password"
                name="confirmPassword"
                id="confirmPassword"
                
                {...confirmPassword}
              />
            </Col>
          </FormGroup>
          <div className="form-actions">
            {error && (
              <>
                <small style={{ color: "red" }}>{error}</small>
                <br />
              </>
            )}
            <br />

            <Col lg={{ offset: 2 }} sm={{ size: 1 }}>
              <Button
                className="mail-reset-btn"
                block
                type="submit"
                value={loading ? "Loading..." : "Login"}
                onClick={handleReset}
                disabled={!validateForm}
              >
                Reset
              </Button>
            </Col>
          </div>
        </Form>

标签: reactjsvalidationreact-hooks

解决方案


更新您validateForm以从表单onSubmit事件中解构密码字段。创建一个errors对象来跟踪存在哪些字段错误。如果errors对象为空,则验证通过,否则设置错误状态。

const validateForm = event => {
  event.preventDefault();

  const { confirmPassword, newPassword } = event.target;
  const errors = {};

  const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;

  if (!regex.test(newPassword.value)) {
    errors.requirementUnmet = "New password does not meet requirements.";
  }

  if (newPassword.value !== confirmPassword.value) {
    errors.passwordMismatch = "Entered passwords do not match.";
  }

  if (!Object.keys(errors).length) {
    alert("password validation successful.");
    setError(null);
    return;
  }

  setError(errors);
};

附加validateForm到表单的onSubmit句柄。

<Form onSubmit={validateForm}>

确保表单中有一个 type="submit" 按钮。

<Button
  className="mail-submit-btn"
  block
  type="submit"
  value={loading ? "Loading..." : "Login"}
>
  Submit
</Button>

更新了 stackblitz虽然我没有帐户,所以复制下面的更新代码。

注意:为了简单起见,我只是简单JSON.stringify(error)的错误,但你会想要更优雅地呈现它。

整个 ResetPassword.js

import React, { useState } from "react";
import {
  Button,
  Form,
  FormGroup,
  Input,
  Col,
  Label,
  Modal,
  ModalHeader,
  ModalBody,
  ModalFooter
} from "reactstrap";

const useFormInput = initialValue => {
  const [value, setValue] = useState(initialValue);

  const handleChange = e => {
    setValue(e.target.value);
  };
  return {
    value,
    onChange: handleChange
  };
};

const ResetPassword = props => {
  // form inputs
  const email = useFormInput("");
  const newPassword = useFormInput("");
  const confirmPassword = useFormInput("");
  // using hooks
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const [modal, setModal] = useState(false);

  const toggle = () => setModal(!modal);

  const validateForm = event => {
    event.preventDefault();

    const { confirmPassword, newPassword } = event.target;
    const errors = {};

    const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9]).{8,}$/;

    if (!regex.test(newPassword.value)) {
      errors.requirementUnmet = "New password does not meet requirements.";
    }

    if (newPassword.value !== confirmPassword.value) {
      errors.passwordMismatch = "Entered passwords do not match.";
    }

    if (!Object.keys(errors).length) {
      alert("password validation successful.");
      setError(null);
      return;
    }

    setError(errors);
  };

  const handleReset = e => {
    e.preventDefault();
    setError(null);
    setLoading(true);
    // some unrelated redux code
  };

  return (
    <div className="mail-reset" id="forgotPassword">
      <div className="mail-reset-content">
        <Form onSubmit={validateForm}>
          <h3 className="form-title">Enter Information</h3>

          <FormGroup row>
            <Label for="Email" sm={2}>
              Email
            </Label>
            <Col sm={4}>
              <Input
                type="email"
                name="email"
                id="Email"
                placeholder="Email"
                aria-label="email address"
                aria-describedby="email address"
                aria-invalid="false"
                {...email}
              />
            </Col>
          </FormGroup>
          <FormGroup row>
            <Label for="newPassword" sm={2}>
              New Password
            </Label>
            <Col sm={4}>
              <Input
                type="password"
                name="password"
                id="newPassword"
                placeholder="New Password"
                aria-label="new password"
                aria-describedby="new password"
                aria-invalid="false"
                {...newPassword}
              />
            </Col>
          </FormGroup>
          <FormGroup row>
            <Label for="confirmPassword" sm={2}>
              Confirm Password
            </Label>
            <Col sm={4}>
              <Input
                type="password"
                name="confirmPassword"
                id="confirmPassword"
                placeholder="Confirm Password"
                aria-label="new password"
                aria-describedby="new password"
                aria-invalid="false"
                {...confirmPassword}
              />
            </Col>
          </FormGroup>

          <div className="modal-wrapper">
            <Col sm={{ size: 4, offset: 2 }}>
              <Button onClick={toggle} className="passwordReqBtn">
                Password Requirements
              </Button>
            </Col>
            <Modal isOpen={modal} toggle={toggle} className="mail-reset-modal">
              <ModalHeader toggle={toggle}>Password Requirements</ModalHeader>
              <ModalBody>
                Your password must contain at least one capital letter, one
                number and one lowercase letter, and it must contain at least 8
                characters
              </ModalBody>
              <ModalFooter>
                <Button onClick={toggle} className="btn-modal pull-right">
                  OK
                </Button>{" "}
              </ModalFooter>
            </Modal>
          </div>

          <div className="form-actions">
            {error && (
              <>
                <small style={{ color: "red" }}>{JSON.stringify(error)}</small>
                <br />
              </>
            )}
            <br />

            <Col lg={{ offset: 2 }} sm={{ size: 1 }}>
              <Button
                className="mail-reset-btn"
                block
                type="submit"
                value={loading ? "Loading..." : "Login"}
              >
                Submit
              </Button>
              <Button
                className="mail-reset-btn"
                block
                type="reset"
                value={loading ? "Loading..." : "Login"}
                onClick={handleReset}
              >
                Reset
              </Button>
            </Col>
          </div>
        </Form>
      </div>
    </div>
  );
};

export default ResetPassword;

推荐阅读