反应动态表单输入字段 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>
);
}
我有一个带有动态输入字段的 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>
);
}