Reactjs 提交按钮禁用问题

Reactjs submit button disable issue

伙计们,我遇到了 提交按钮禁用 功能

的问题

我设置了3个条件:

  1. 密码应大于8个字符
  2. 至少应包含 1 个数字
  3. 客户应点击条款和隐私

只有满足这 3 个条件,布尔值“allvalid”才会被设置为 true

问题: 我发现在满足所有条件后,按钮仍然处于禁用状态 但是当我在密码提交按钮中再输入 1 个字符时,我删除了仍然有效的 1 个字符(现在是 8 个字符),但是当我再删除一个(现在是 7 个字符)时,提交按钮仍然启用,只有当我减少到 6 它再次被禁用

我希望它在满足所有条件时准确启用,在不满足时立即禁用

这是代码

export function SignupForm(props) {
  const { switchToSignin } = useContext(AccountContext);
  const [passwordOne, setPasswordOne] = useState("")

  // booleans for password validations
  const [containsN, setContainsN] = useState(false) // number
  const [contains8C, setContains8C] = useState(false) // min 8 characters

  // checks all validations are true
  const [allValid, setAllValid] = useState(false)
  const [terms,setTerms]=useState(false)
  // Client shall check on the terms otherwise submit button is disabled
  const checkTerms=() => {
    setTerms(true)
  }
  const validatePassword = () => {
    // has number
    if (/\d/.test(passwordOne)) setContainsN(true)
    else setContainsN(false)

    // has 8 characters
    if (passwordOne.length >= 8) setContains8C(true)
    else setContains8C(false)

     // all validations passed
    if (containsN  && contains8C && terms) setAllValid(true)
    else setAllValid(false)
  }

  const handleSubmit=(e)=> {
    alert('Submitted' );
    e.preventDefault();
  }

  return (
    <BoxContainer>
        <FormContainer onSubmit={handleSubmit}>
          <Input type="text" placeholder="Full Name" />
          <Input type="email" placeholder="Email" />
          <Input type="password" placeholder="Password"
          value={passwordOne} 
                          onChange={e=>setPasswordOne(e.target.value)} 
                          onKeyUp={validatePassword}
          />
          <column>
            <Condition>
              <img className="check" src={contains8C?check:uncheck}  alt="icon1" />
                8 Characters min.
              <img className="check" src={containsN?check:uncheck}  alt="icon2" />
              One number
            </Condition>
          </column>
          <column>
            <Checkbox>
              <input type="checkbox" onClick={checkTerms}></input>
            </Checkbox>
            <Terms align='left'>By creating account, you agree to accept our Privacy policy, Terms of Service and Notification settings.</Terms>
          </column>
          
          <Marginer direction="vertical" margin={10} />  
          <SubmitButton type="submit" value="Submit" disabled={!allValid}>Signup</SubmitButton>
        </FormContainer>)

我认为这是由于 react.Check allvalid 状态值中挂钩的异步行为,因为它取决于其他 states.Make 确保 allvalid 状态在更新状态后正确更新它是依赖的。

我检查了你的存储库,我想我发现了问题。

首先,您的 SubmitButton 组件禁用 属性 无法正常工作。

这就是我将其更改为基本 HTML 按钮以确保正常处理值的原因。

新的喜欢的按钮应该是这样的:

<button type="submit" value="Submit" disabled={!allValid}>Signup</button>

关于复选框的另一点。您需要处理是否已选中,因此新的复选框按钮应如下所示:

<input type="checkbox" onClick={(e)=>checkTerms(e)}></input>

最后一步您需要在表单中跟踪验证值,您应该再次更新状态以禁用和启用按钮。为此,您需要像这样使用 useEffect 钩子:

 useEffect(()=>{
    // Track all local states and validate the term
    validatePassword()
 },[passwordOne,terms,containsN,contains8C,validatePassword]);

新的 checkTerms 函数将是:

const checkTerms=(e) => {
   setTerms(e.target.checked)
}

我会把最后的 signupForm.jsx 给你:

import React, { useState,useEffect } from 'react';
import { useContext } from "react";
import {
  BoldLink,
  BoxContainer,
  FormContainer,
  Input,
  MutedLink
} from "./common";
import { Marginer } from "../marginer";
import { AccountContext } from "./accountContext";
import styled from "styled-components";
import check from "./images/check.png";
import uncheck from "./images/uncheck.png";

const Terms = styled.h5`
  width: 250px;
  color: #000000;
  font-weight: 500;
  font-size: 10px;
  z-index: 10;
  margin: 0;
  margin-top: 7px;
`;

const Condition= styled.div`
  background: #fff;
  padding: 3px;
  width: 250px;
  height: 30px;
  float: left;
  flex:50%;
  font-weight: 500;
  font-size: 9px;
  color: #000;
  margin: 2px;
`;

const Checkbox= styled.div`
  background: #fff;
  padding: 3px;
  width: 30px;
  height: 10px;
  float: left;
  flex:50%;
  font-weight: 500;
  font-size: 9px;
  color: #000;
  margin: 2px;
`;


export function SignupForm(props) {
  const { switchToSignin } = useContext(AccountContext);
  const [passwordOne, setPasswordOne] = useState("")

  // booleans for password validations
  const [containsN, setContainsN] = useState(false) // number
  const [contains8C, setContains8C] = useState(false) // min 8 characters

  // checks all validations are true
  const [allValid, setAllValid] = useState(false)
  const [terms,setTerms]=useState(false)
  // labels and state boolean corresponding to each validation
  const checkTerms=(e) => {
    setTerms(e.target.checked)
  }

  const validatePassword = () => {
    // has number
    if (/\d/.test(passwordOne)) setContainsN(true)
    else setContainsN(false)

    // has 8 characters
    if (passwordOne.length >= 8) setContains8C(true)
    else setContains8C(false)

     // all validations passed
    if (containsN  && contains8C && terms) setAllValid(true)
    else setAllValid(false)
  }

  const handleSubmit=(e)=> {
    alert('Submitted' );
    e.preventDefault();
  }

  useEffect(()=>{
    // Track all local states and validate the term
    validatePassword()
  },[passwordOne,terms,containsN,contains8C,validatePassword]);

  return (
    <BoxContainer>
        <FormContainer onSubmit={handleSubmit}>
          <Input type="text" placeholder="Full Name" />
          <Input type="email" placeholder="Email" />
          <Input type="password" placeholder="Password"
          value={passwordOne}
                          onChange={e=>setPasswordOne(e.target.value)}
                          onKeyUp={validatePassword}
          />
          <column>
            <Condition>
              <img className="check" src={contains8C?check:uncheck}  alt="icon1" />
                8 Characters min.
              <img className="check" src={containsN?check:uncheck}  alt="icon2" />
              One number
            </Condition>
          </column>
          <column>
            <Checkbox>
              <input type="checkbox" onClick={(e)=>checkTerms(e)}></input>
            </Checkbox>
            <Terms align='left'>By creating account, you agree to accept our Privacy policy, Terms of Service and Notification settings.</Terms>
          </column>

          <Marginer direction="vertical" margin={10} />
          <button type="submit" value="Submit" disabled={!allValid}>Signup</button>
        </FormContainer>
      <Marginer direction="vertical" margin="1em" />
      <MutedLink href="#">
        Already have an account?
        <BoldLink href="#" onClick={switchToSignin}>
          Signin
        </BoldLink>
      </MutedLink>
    </BoxContainer>
  );
}