React 表单如何根据切换获取用户数据 on/off
React form how to get user data based on a toggle on/off
我在 React JS 中有一个表单 toggle/switch。如果 toggle/switch 打开,则屏幕上会出现两个输入。因此,如果用户输入输入并且 toggle/switch 打开并保持打开状态,我想获取用户数据。因此,如果用户输入输入但他再次 toggles/switches 关闭,则输入值将被重置,当他保存表单时,我必须得到空的用户数据(我得到初始值)。我怎样才能实现这样的目标?如果切换按钮为假,我正在检查提交处理程序并将使用状态设置为初始值,但它不起作用。
我的代码:
Form.js
import React, { useRef, useState } from "react";
import Wrapper from "./UI/Wrapper";
import Switch from '@mui/material/Switch';
import "./Form.css";
const Form = () => {
const [showCertification, setShowCertification] = useState(false);
const [enteredCodecert, setEnteredCodecert] = useState('');
const codecertRef = useRef();
const [codesteps, setCodesteps] = useState([{ value: null }]);
const codestepsRef = useRef();
const enteredCodecertIsValid = showCertification && enteredCodecert.trim() !== '';
const codecertInputIsInvalid = !enteredCodecertIsValid;
const codestepsIsValid = showCertification && codesteps.length >= 1 && codesteps.every(codestep => codestep.value !== null && codestep.value.trim() !== '');
const codestepInputIsInvalid = !codestepsIsValid;
const showCertificationHandler = (event) => {
setShowCertification(prevState => !prevState);
if (!showCertification) {
setEnteredCodecert('');
setCodesteps([{value: null}]);
}
}
const codecertChangeHandler = (event) => {
setEnteredCodecert(event.target.value);
}
const stepChangeHandler = (i, event) => {
const values = [...codesteps];
values[i].value = event.target.value;
setCodesteps(values);
}
const addStepHandler = (event) => {
event.preventDefault();
const values = [...codesteps];
values.push({ value: null });
setCodesteps(values);
}
const removeStepHandler = (i, event) => {
event.preventDefault();
const values = [...codesteps];
values.splice(i, 1);
setCodesteps(values);
}
const submitHandler = (event) => {
event.preventDefault();
if (!enteredCodecertIsValid && showCertification) {
codecertRef.current.focus();
return;
}
if (!codestepsIsValid && showCertification) {
if (codesteps.length >= 1) {
codestepsRef.current.focus();
return;
}
return;
}
if (showCertification === false) {
setEnteredCodecert('');
setCodesteps([{value: null}]);
}
console.log(enteredCodecert);
console.log(codesteps);
}
return (
<Wrapper>
<form onSubmit={submitHandler}>
<fieldset className={`${(showCertification && codecertInputIsInvalid) || (showCertification && codestepInputIsInvalid) ? 'govgr-form-group__error' : '' }`}>
<legend><h3 className="govgr-heading-m">Certifications</h3></legend>
<Switch id="certification" checked={showCertification} onClick={showCertificationHandler} inputProps={{ 'aria-label': 'controlled' }} />
<label className="govgr-label govgr-!-font-weight-bold cert-label" htmlFor="certification">Certification</label>
{showCertification && (
<div>
<div className="govgr-form-group">
<label className="govgr-label govgr-!-font-weight-bold" htmlFor="codecert">Code Certification*</label>
{codecertInputIsInvalid && <p className="govgr-error-message"><span className="govgr-visually-hidden">Λάθος:</span>Code Certification is required.</p>}
<input className={`govgr-input govgr-!-width-three-quarter ${codecertInputIsInvalid ? 'govgr-error-input' : ''}`} id="codecert" name="codecert" type="text" value={enteredCodecert} ref={codecertRef} onChange={codecertChangeHandler} />
</div>
<div className="govgr-form-group">
<label className="govgr-label govgr-!-font-weight-bold" htmlFor="codestep">Code STEPS*</label>
{codestepInputIsInvalid && <p className="govgr-error-message"><span className="govgr-visually-hidden">Λάθος:</span>Code STEPS are required.</p>}
{codesteps.map((field, idx) => {
return (
<div key={`${field}-${idx}`}>
<div className="flex-row">
<input className={`govgr-input govgr-input--width-10 input-step ${codestepInputIsInvalid ? 'govgr-error-input' : ''}`} id="codestep" type="text" ref={codestepsRef} value={field.value || ""} onChange={e => stepChangeHandler(idx, e)} />
<button className="govgr-btn govgr-btn-warning remove-step" onClick={(e) => removeStepHandler(idx, e)}>Χ</button>
</div>
</div>
);
})}
<button className="govgr-btn govgr-btn-secondary button-step" onClick={addStepHandler}>Add Code Step</button>
</div>
</div>
)}
</fieldset>
<button className="govgr-btn govgr-btn-primary btn-center" type="submit">Save</button>
</form>
</Wrapper>
);
};
export default Form;
问题是,在 showCertificationHandler
中,当您切换 showCertification
时,您期望状态更新是立即的。
const showCertificationHandler = (event) => {
setShowCertification(prevState => !prevState);
if (!showCertification) {
setEnteredCodecert('');
setCodesteps([{value: null}]);
}
}
然而,React 状态更新不是这种情况。 React 状态更新已排队并异步处理。
要解决,请将“重置”逻辑移动到 useEffect
挂钩中,该挂钩依赖于 showCertification
状态。
const showCertificationHandler = () => {
setShowCertification((prevState) => !prevState);
};
useEffect(() => {
if (!showCertification) {
setEnteredCodecert("");
setCodesteps([{ value: null }]);
}
}, [showCertification]);
出于与上述相同的原因,当重置 submitHandler
中的状态时,它们会被排队并异步处理,因此控制台在之后立即记录状态只会记录当前渲染周期的状态值,而不是它们将在随后的渲染周期中出现。您可以从 submitHandler
.
中删除“重置”逻辑
const submitHandler = (event) => {
event.preventDefault();
if (!enteredCodecertIsValid && showCertification) {
codecertRef.current.focus();
return;
}
if (!codestepsIsValid && showCertification) {
if (codesteps.length >= 1) {
codestepsRef.current.focus();
return;
}
return;
}
console.log({enteredCodecert, codesteps});
};
我在 React JS 中有一个表单 toggle/switch。如果 toggle/switch 打开,则屏幕上会出现两个输入。因此,如果用户输入输入并且 toggle/switch 打开并保持打开状态,我想获取用户数据。因此,如果用户输入输入但他再次 toggles/switches 关闭,则输入值将被重置,当他保存表单时,我必须得到空的用户数据(我得到初始值)。我怎样才能实现这样的目标?如果切换按钮为假,我正在检查提交处理程序并将使用状态设置为初始值,但它不起作用。
我的代码:
Form.js
import React, { useRef, useState } from "react";
import Wrapper from "./UI/Wrapper";
import Switch from '@mui/material/Switch';
import "./Form.css";
const Form = () => {
const [showCertification, setShowCertification] = useState(false);
const [enteredCodecert, setEnteredCodecert] = useState('');
const codecertRef = useRef();
const [codesteps, setCodesteps] = useState([{ value: null }]);
const codestepsRef = useRef();
const enteredCodecertIsValid = showCertification && enteredCodecert.trim() !== '';
const codecertInputIsInvalid = !enteredCodecertIsValid;
const codestepsIsValid = showCertification && codesteps.length >= 1 && codesteps.every(codestep => codestep.value !== null && codestep.value.trim() !== '');
const codestepInputIsInvalid = !codestepsIsValid;
const showCertificationHandler = (event) => {
setShowCertification(prevState => !prevState);
if (!showCertification) {
setEnteredCodecert('');
setCodesteps([{value: null}]);
}
}
const codecertChangeHandler = (event) => {
setEnteredCodecert(event.target.value);
}
const stepChangeHandler = (i, event) => {
const values = [...codesteps];
values[i].value = event.target.value;
setCodesteps(values);
}
const addStepHandler = (event) => {
event.preventDefault();
const values = [...codesteps];
values.push({ value: null });
setCodesteps(values);
}
const removeStepHandler = (i, event) => {
event.preventDefault();
const values = [...codesteps];
values.splice(i, 1);
setCodesteps(values);
}
const submitHandler = (event) => {
event.preventDefault();
if (!enteredCodecertIsValid && showCertification) {
codecertRef.current.focus();
return;
}
if (!codestepsIsValid && showCertification) {
if (codesteps.length >= 1) {
codestepsRef.current.focus();
return;
}
return;
}
if (showCertification === false) {
setEnteredCodecert('');
setCodesteps([{value: null}]);
}
console.log(enteredCodecert);
console.log(codesteps);
}
return (
<Wrapper>
<form onSubmit={submitHandler}>
<fieldset className={`${(showCertification && codecertInputIsInvalid) || (showCertification && codestepInputIsInvalid) ? 'govgr-form-group__error' : '' }`}>
<legend><h3 className="govgr-heading-m">Certifications</h3></legend>
<Switch id="certification" checked={showCertification} onClick={showCertificationHandler} inputProps={{ 'aria-label': 'controlled' }} />
<label className="govgr-label govgr-!-font-weight-bold cert-label" htmlFor="certification">Certification</label>
{showCertification && (
<div>
<div className="govgr-form-group">
<label className="govgr-label govgr-!-font-weight-bold" htmlFor="codecert">Code Certification*</label>
{codecertInputIsInvalid && <p className="govgr-error-message"><span className="govgr-visually-hidden">Λάθος:</span>Code Certification is required.</p>}
<input className={`govgr-input govgr-!-width-three-quarter ${codecertInputIsInvalid ? 'govgr-error-input' : ''}`} id="codecert" name="codecert" type="text" value={enteredCodecert} ref={codecertRef} onChange={codecertChangeHandler} />
</div>
<div className="govgr-form-group">
<label className="govgr-label govgr-!-font-weight-bold" htmlFor="codestep">Code STEPS*</label>
{codestepInputIsInvalid && <p className="govgr-error-message"><span className="govgr-visually-hidden">Λάθος:</span>Code STEPS are required.</p>}
{codesteps.map((field, idx) => {
return (
<div key={`${field}-${idx}`}>
<div className="flex-row">
<input className={`govgr-input govgr-input--width-10 input-step ${codestepInputIsInvalid ? 'govgr-error-input' : ''}`} id="codestep" type="text" ref={codestepsRef} value={field.value || ""} onChange={e => stepChangeHandler(idx, e)} />
<button className="govgr-btn govgr-btn-warning remove-step" onClick={(e) => removeStepHandler(idx, e)}>Χ</button>
</div>
</div>
);
})}
<button className="govgr-btn govgr-btn-secondary button-step" onClick={addStepHandler}>Add Code Step</button>
</div>
</div>
)}
</fieldset>
<button className="govgr-btn govgr-btn-primary btn-center" type="submit">Save</button>
</form>
</Wrapper>
);
};
export default Form;
问题是,在 showCertificationHandler
中,当您切换 showCertification
时,您期望状态更新是立即的。
const showCertificationHandler = (event) => {
setShowCertification(prevState => !prevState);
if (!showCertification) {
setEnteredCodecert('');
setCodesteps([{value: null}]);
}
}
然而,React 状态更新不是这种情况。 React 状态更新已排队并异步处理。
要解决,请将“重置”逻辑移动到 useEffect
挂钩中,该挂钩依赖于 showCertification
状态。
const showCertificationHandler = () => {
setShowCertification((prevState) => !prevState);
};
useEffect(() => {
if (!showCertification) {
setEnteredCodecert("");
setCodesteps([{ value: null }]);
}
}, [showCertification]);
出于与上述相同的原因,当重置 submitHandler
中的状态时,它们会被排队并异步处理,因此控制台在之后立即记录状态只会记录当前渲染周期的状态值,而不是它们将在随后的渲染周期中出现。您可以从 submitHandler
.
const submitHandler = (event) => {
event.preventDefault();
if (!enteredCodecertIsValid && showCertification) {
codecertRef.current.focus();
return;
}
if (!codestepsIsValid && showCertification) {
if (codesteps.length >= 1) {
codestepsRef.current.focus();
return;
}
return;
}
console.log({enteredCodecert, codesteps});
};