反应状态钩子,并使用效果影响状态更新的意外行为

时间:2019-06-10 19:42:18

标签: reactjs react-hooks

所以我有一个我以前在Vue中做过的项目,现在正在React(w / hooks)中进行学习。我遇到了一些问题,担心我没有以正确的方式进行操作(确定我不是)。

我遇到的最大问题之一是通过onchange和onblur更新状态。很多时候,状态值会落后一格。我发现使用旧类组件可以在setState中使用回调。 我正在尝试在用户更新字段时显示/隐藏即时表单验证反馈。

使用钩子应该使用useEffect来完成。我现在正在“工作”,但似乎渲染的次数超过了应有的次数。我可以知道它运行两次checkValues()来显示当前状态值的事实。

我误解的性质的一个示例是,如果我不将setinValid(validateForm());放在onchange和useEffect中。它不会更新inValid的状态,后者会禁用/启用提交按钮。这对我来说似乎是多余的,我不确定为什么它会“按原样”工作。

任何对如何正确执行我正在尝试的操作的帮助/见解将不胜感激。

https://codesandbox.io/s/user-listing-in-react-9ip4t?fontsize=14&module=%2Fsrc%2Fcomponents%2FUser%2FUserAdd.js

import React from "react";
import { Link } from "react-router-dom";
// import { saveUserToLocalStorage } from "../../utils/StorageHelper";
// import { User } from "../../utils/UserClass";

const UserAdd = props => {
  const [userName, setuserName] = React.useState("");
  const [userAge, setuserAge] = React.useState("");
  const [userEmail, setuserEmail] = React.useState("");
  const [inValid, setinValid] = React.useState(true);
  const [errors, setErrors] = React.useState({
    name: [],
    age: [],
    email: []
  });
  React.useEffect(() => {
    checkValues();
    setinValid(validateForm());
  }, [userName, userAge, userEmail, inValid]);
  const validateForm = () => {
    if (isNaN(userAge)) {
      return true;
    }
    if (!userName || !userAge || !userEmail) {
      return true;
    }
    if (!validateEmail(userEmail)) {
      return true;
    }
    return false;
  };
  function checkIndividualErrors() {
    if (userName.length === 0) {
      setErrors({ ...errors, name: ["User name is required"] });
    } else {
      setErrors({ ...errors, name: [] });
    }
  }
  const checkValues = () => {
    console.log(
      "username:",
      userName,
      "age:",
      userAge,
      "useremail: ",
      userEmail,
      "invalid:",
      inValid
    );
  };
  const validateEmail = mail => {
    if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(mail)) {
      return true;
    }
    return false;
  };

  return (
    <div>
      <h2 class="line-container">
        <span>Add a new User</span>
      </h2>
      <hr />
      <div class="field is-horizontal">
        <div class="field-label is-normal">
          <label class="label">Name</label>
        </div>
        <div class="field-body">
          <div class="field">
            <p class="control">
              <input
                class="input"
                type="text"
                name="name"
                placeholder="Name"
                value={userName}
                onChange={e => {
                  setuserName(e.target.value);
                  setinValid(validateForm());
                  checkIndividualErrors();
                }}
                onBlur={checkIndividualErrors}
              />

              <span class="error">{errors.name}</span>
            </p>
          </div>
        </div>
      </div>

      <div class="field is-horizontal">
        <div class="field-label is-normal">
          <label class="label">Age</label>
        </div>
        <div class="field-body">
          <div class="field">
            <p class="control">
              <input
                class="input"
                type="text"
                name="age"
                placeholder="Age"
                value={userAge}
                onChange={e => {
                  setuserAge(e.target.value);
                  setinValid(validateForm());
                  // checkIndividualErrors not fully implemented yet
                }}
              />
              <span class="error" />
            </p>
          </div>
        </div>
      </div>

      <div class="field is-horizontal">
        <div class="field-label is-normal">
          <label class="label">Email</label>
        </div>
        <div class="field-body">
          <div class="field">
            <p class="control">
              <input
                class="input"
                type="email"
                name="email"
                placeholder="Email"
                value={userEmail}
                onChange={e => {
                  setuserEmail(e.target.value);
                  setinValid(validateForm());
                  // checkIndividualErrors not fully implemented yet
                }}
              />
              <span class="error" />
            </p>
          </div>
        </div>
      </div>

      <p class="" style={{ margin: "0 auto" }}>
        <button
          disabled={inValid}
          class="button is-primary"
          style={{ marginRight: "10px" }}
        >
          Create
        </button>
        <Link to="/" class="button">
          Cancel
        </Link>
        <Link to="/" class="goBack">
          <span style={{ fontSize: "20px" }}>←</span>
        </Link>
      </p>
    </div>
  );
};
export default UserAdd;

0 个答案:

没有答案