反应动态表单输入字段 typeError undefined trim()

React dynamic form input fields typeError undefined trim()

我有一个带有动态输入字段的 React 表单,用户可以添加和删除输入字段。所有输入都是必需的。如果填写了所有输入字段并提交了表单,那么我 console.log() 一个包含值的数组,否则空输入将获得焦点。问题是,如果我在输入字段内使用空格(退格),则可以提交表单,但我不希望这样。我怎样才能解决这个问题?我尝试使用 trim() 方法 (const registriesIsValid = registryValues.every((registry)=>registry.name.trim() !== "" && registry.code.trim() !== "");) 但我收到“typeError 无法读取未定义的属性(读取 'trim')”。

下面我的代码没有 trim 方法。

App.js

import React, { useState, useRef } from "react";
import Wrapper from "./Wrapper";
import "./styles.css";

export default function App() {
  const [registryValues, setRegistryValues] = useState([]);
  const [registryValuesTouched, setRegistryValuesTouched] = useState(false);
  const fieldRef = useRef();
  // const registriesRef = useRef();

  const registriesIsValid = registryValues.every(
    (registry) => registry.name !== "" && registry.code !== ""
  );
  const registriesInputIsInvalid = !registriesIsValid;

  let handleRegistryChange = (i, event) => {
    setRegistryValuesTouched(true);
    let newRegistryValues = [...registryValues];
    if (event.target.name === "name") {
      newRegistryValues[i].registry["name"] = event.target.value;
    }
    if (event.target.name === "code") {
      newRegistryValues[i].code = event.target.value;
    }
    // newRegistryValues[i][event.target.name] = event.target.value;
    setRegistryValues(newRegistryValues);
  };

  let addRegistryFields = (event) => {
    event.preventDefault();
    setRegistryValues([
      ...registryValues,
      { registry: { name: "" }, code: "" }
    ]);
  };

  let removeRegistryFields = (i, event) => {
    event.preventDefault();
    let newRegistryValues = [...registryValues];
    newRegistryValues.splice(i, 1);
    setRegistryValues(newRegistryValues);
  };

  const submitHandler = (event) => {
    event.preventDefault();
    setRegistryValuesTouched(true);

    for (let elem of fieldRef.current.elements) {
      if (elem.dataset.required && !elem.value) {
        elem.focus();
        return;
      }
    }

    console.log(registryValues);

    setRegistryValuesTouched(false);
  };

  return (
    <Wrapper>
      <form onSubmit={submitHandler} ref={fieldRef}>
        <fieldset>
          <legend>
            <h3 className="govgr-heading-m margin-top">Registries</h3>
          </legend>
          <div
            className={`${
              registriesInputIsInvalid ? "govgr-form-group__error" : ""
            }`}
          >
            {registriesInputIsInvalid && (
              <p className="govgr-error-message">
                <span className="govgr-visually-hidden">Λάθος:</span>All fields
                are required.
              </p>
            )}
            {registriesInputIsInvalid && (
              <p className="govgr-error-message">
                <span className="govgr-visually-hidden">Λάθος:</span>You must
                fill in registry Name and registry Code.
              </p>
            )}
            {registryValues.map((element, index) => (
              <div key={index} className="flex-row registry-margin-bottom">
                <div className="registry-flex-basis">
                  <div className="govgr-form-group">
                    <label
                      className="govgr-label govgr-!-font-weight-bold"
                      htmlFor="name"
                    >
                      Registry Name*
                    </label>
                    <input
                      className={`govgr-input govgr-!-width-three-quarter ${
                        element.registry["name"].trim() === ""
                          ? "govgr-error-input"
                          : ""
                      }`}
                      type="text"
                      name="name"
                      data-required="true"
                      value={element.registry["name"] || ""}
                      onChange={(e) => handleRegistryChange(index, e)}
                    />
                  </div>

                  <div className="govgr-form-group">
                    <label
                      className="govgr-label govgr-!-font-weight-bold"
                      htmlFor="code"
                    >
                      Registry Code*
                    </label>
                    <input
                      className={`govgr-input govgr-!-width-three-quarter ${
                        element.code.trim() === "" ? "govgr-error-input" : ""
                      }`}
                      type="text"
                      name="code"
                      data-required="true"
                      value={element.code || ""}
                      onChange={(e) => handleRegistryChange(index, e)}
                    />
                  </div>
                </div>
                <button
                  className="govgr-btn govgr-btn-warning remove-registry"
                  onClick={(e) => removeRegistryFields(index, e)}
                >
                  X
                </button>
              </div>
            ))}
          </div>
        </fieldset>
        <button
          className="govgr-btn govgr-btn-secondary button-registry"
          onClick={addRegistryFields}
        >
          Add Registry
        </button>

        <button
          className="govgr-btn govgr-btn-primary btn-center"
          type="submit"
        >
          Save
        </button>
      </form>
    </Wrapper>
  );
}

通过简单的检查看起来很简单:

if (registry.name && registry.name.trim() !== "")
... 

&& 的右手只有在左手 returns 为真时才会被评估。
这与 || 不同,后者始终对左手和右手进行评估。

我修好了。实际上,在我的 submitHandler 中,我忘记检查 (if !registriesIsValid){...} .

此外,我的注册表对象具有不同的结构。所以我将验证更改为:

const registriesIsValid = registryValues.every((registry)=>registry.registry["name"].trim() !== "" && registry.code.trim() !== "");

App.js

import React, { useState, useRef } from "react";
import Wrapper from "./Wrapper";
import "./styles.css";

export default function App() {
  const [registryValues, setRegistryValues] = useState([]);
  const [registryValuesTouched, setRegistryValuesTouched] = useState(false);
  const fieldRef = useRef();
  // const registriesRef = useRef();
   
  //1st change
  const registriesIsValid = registryValues.every(
    (registry) => registry.registry["name"].trim() !== "" && registry.code.trim() !== ""
  );
  const registriesInputIsInvalid = !registriesIsValid;

  let handleRegistryChange = (i, event) => {
    setRegistryValuesTouched(true);
    let newRegistryValues = [...registryValues];
    if (event.target.name === "name") {
      newRegistryValues[i].registry["name"] = event.target.value;
    }
    if (event.target.name === "code") {
      newRegistryValues[i].code = event.target.value;
    }
    // newRegistryValues[i][event.target.name] = event.target.value;
    setRegistryValues(newRegistryValues);
  };

  let addRegistryFields = (event) => {
    event.preventDefault();
    setRegistryValues([
      ...registryValues,
      { registry: { name: "" }, code: "" }
    ]);
  };

  let removeRegistryFields = (i, event) => {
    event.preventDefault();
    let newRegistryValues = [...registryValues];
    newRegistryValues.splice(i, 1);
    setRegistryValues(newRegistryValues);
  };

  const submitHandler = (event) => {
    event.preventDefault();
    setRegistryValuesTouched(true);


    //2nd change
    if (!registriesIsValid) {
      for (let elem of fieldRef.current.elements) {
        if (elem.dataset.required && !elem.value.trim()) {
          elem.focus();
          return;
        }
      }
      return;
    }
    
    console.log(registryValues);

    setRegistryValuesTouched(false);
  };

  return (
    <Wrapper>
      <form onSubmit={submitHandler} ref={fieldRef}>
        <fieldset>
          <legend>
            <h3 className="govgr-heading-m margin-top">Registries</h3>
          </legend>
          <div
            className={`${
              registriesInputIsInvalid ? "govgr-form-group__error" : ""
            }`}
          >
            {registriesInputIsInvalid && (
              <p className="govgr-error-message">
                <span className="govgr-visually-hidden">Λάθος:</span>All fields
                are required.
              </p>
            )}
            {registriesInputIsInvalid && (
              <p className="govgr-error-message">
                <span className="govgr-visually-hidden">Λάθος:</span>You must
                fill in registry Name and registry Code.
              </p>
            )}
            {registryValues.map((element, index) => (
              <div key={index} className="flex-row registry-margin-bottom">
                <div className="registry-flex-basis">
                  <div className="govgr-form-group">
                    <label
                      className="govgr-label govgr-!-font-weight-bold"
                      htmlFor="name"
                    >
                      Registry Name*
                    </label>
                    <input
                      className={`govgr-input govgr-!-width-three-quarter ${
                        element.registry["name"].trim() === ""
                          ? "govgr-error-input"
                          : ""
                      }`}
                      type="text"
                      name="name"
                      data-required="true"
                      value={element.registry["name"] || ""}
                      onChange={(e) => handleRegistryChange(index, e)}
                    />
                  </div>

                  <div className="govgr-form-group">
                    <label
                      className="govgr-label govgr-!-font-weight-bold"
                      htmlFor="code"
                    >
                      Registry Code*
                    </label>
                    <input
                      className={`govgr-input govgr-!-width-three-quarter ${
                        element.code.trim() === "" ? "govgr-error-input" : ""
                      }`}
                      type="text"
                      name="code"
                      data-required="true"
                      value={element.code || ""}
                      onChange={(e) => handleRegistryChange(index, e)}
                    />
                  </div>
                </div>
                <button
                  className="govgr-btn govgr-btn-warning remove-registry"
                  onClick={(e) => removeRegistryFields(index, e)}
                >
                  X
                </button>
              </div>
            ))}
          </div>
        </fieldset>
        <button
          className="govgr-btn govgr-btn-secondary button-registry"
          onClick={addRegistryFields}
        >
          Add Registry
        </button>

        <button
          className="govgr-btn govgr-btn-primary btn-center"
          type="submit"
        >
          Save
        </button>
      </form>
    </Wrapper>
  );
}