【问题标题】:why doesn't validating input on eventListener work?为什么在 eventListener 上验证输入不起作用?
【发布时间】:2020-10-28 16:13:12
【问题描述】:

你能帮我让这个沙盒工作吗? 我想念一些东西。

当密码或登录名的长度超过 3 时,我希望在输入附近看到“GOOD”而不是“FAIL”。

这里是链接:https://codesandbox.io/s/competent-bogdan-5604u?file=/src/App.js

谢谢!

【问题讨论】:

  • 相关代码应该在问题中而不是场外。
  • 除此之外,您正在使用事件侦听器进行反应输入有点危险。只需将该逻辑放入更改处理函数中,它们已经是受控输入。
  • 已经试过了,还是不行:/

标签: reactjs addeventlistener


【解决方案1】:

有一些问题,但它们都来自同一个根 - 状态更新不会立即发生。

问题一是调用setState后不能立即使用更新的状态。这会导致您的验证逻辑使用 previous 渲染中的表单值执行。

问题二是如果你连续两次调用状态更新函数,它只会使用最后一个值。因此,在您的验证逻辑中,您根据login 的值调用一次setFormError,然后根据password 的值调用一次。这意味着永远不会使用由login 逻辑确定的值。

我写了一个例子,说明你可以正确地写这个。

示例之一是在每次输入更改时调用的函数:

const { useState } = React;

const MyInput = (props) => {
  return (
    <input {...props} style={{ border: "1px solid red", outline: "none" }} />
  );
};

const Example = () => {
  const [form, setForm] = useState({
    login: "",
    password: ""
  });
  const [formError, setFormError] = useState({
    isValidLogin: "FAIL",
    isValidPassword: "FAIL"
  });

  const handleValidateForm = (newForm) => {
    let newValid = {...formError}; // Use a new object so we only update state once
    
    if (newForm.login.length > 3) {
      newValid.isValidLogin = "GOOD"
    } else {
      newValid.isValidLogin = "FAIL"
    }
    if (newForm.password.length > 3) {
      newValid.isValidPassword = "GOOD"
    } else {
      newValid.isValidPassword = "FAIL"
    }
    
    setFormError(newValid);
  };

  const onChange = (e) => {
    e.preventDefault();
    const { name, value } = e.target;
    
    const newForm = {...form, [name]: value}; // Set to new object

    setForm(newForm);
    
    handleValidateForm(newForm); // Send the new object so its up-to-date
  };

  return (
    <div>
      <div>
        <MyInput type="text" name="login" onChange={onChange} />{" "}
        {formError.isValidLogin}
        <br />
        <MyInput type="text" name="password" onChange={onChange} />{" "}
        {formError.isValidPassword}
      </div>
    </div>
  );
};


ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

另一种方法是将验证移至useEffect

const { useState, useEffect } = React;

const MyInput = (props) => {
  return (
    <input {...props} style={{ border: "1px solid red", outline: "none" }} />
  );
};

const Example = () => {
  const [form, setForm] = useState({
    login: "",
    password: ""
  });
  const [formError, setFormError] = useState({
    isValidLogin: "FAIL",
    isValidPassword: "FAIL"
  });

  useEffect(() => {
    let newValid = {...formError}; // Use a new object so we only update state once
    
    if (form.login.length > 3) {
      newValid.isValidLogin = "GOOD"
    } else {
      newValid.isValidLogin = "FAIL"
    }
    if (form.password.length > 3) {
      newValid.isValidPassword = "GOOD"
    } else {
      newValid.isValidPassword = "FAIL"
    }
    
    setFormError(newValid);
  }, [form]); // Runs every time the form changes

  const onChange = (e) => {
    e.preventDefault();
    const { name, value } = e.target;
    
    setForm({...form, [name]: value});
  };

  return (
    <div>
      <div>
        <MyInput type="text" name="login" onChange={onChange} />{" "}
        {formError.isValidLogin}
        <br />
        <MyInput type="text" name="password" onChange={onChange} />{" "}
        {formError.isValidPassword}
      </div>
    </div>
  );
};


ReactDOM.render(<Example />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

效果一样,看你喜欢哪种模式。

【讨论】:

    猜你喜欢
    • 2021-09-07
    • 2019-12-23
    • 1970-01-01
    • 2016-08-24
    • 1970-01-01
    • 2017-07-03
    • 1970-01-01
    • 2013-05-27
    • 2018-11-26
    相关资源
    最近更新 更多