javascript - 在 React TS 中對來自 'reactstrap' 的 欄位應用自訂驗證時舊值重新出現
我在使用 React TS 時遇到舊值重新出現的問題。我先提供我的程式碼,這樣你也可以檢查它:
const initialState = {
name: '',
};
const [registeredValidations, setRegisteredValidations] = useState({} as RegisteredValidationMap);
const [formData, setFormData] = useState({
...initialState,
name: requestStore.formData.name[0] || initialState.name
});
這裡是我為輸入欄位自訂實作的驗證呼叫以及驗證內容:
<ValidatedInput
name="name"
value={formData.name}
onChange={handleOnChange}
validations={[GenericInputValidation]}
isOptional={!fieldsRequired}
setRegisteredValidations={setRegisteredValidations}
registeredValidations={registeredValidations}
/>
<Row>
<Navigation handleOnNextClick={handleOnNextClick} registeredValidations={registeredValidations} />
</Row>
onChange 監聽器的實作方式:
const handleOnChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prevState => ({
...prevState,
[name]: value,
}));
};
通用輸入驗證:
export class GenericInputValidation extends Validation {
// eslint-disable-next-line @typescript-eslint/require-await
static async validate(props: ValidationProps): Promise<string[]> {
const errors = [];
if (props.newValue === '' && !props.isOptional) {
errors.push(translate('error.missing-value'));
}
return errors;
}
}
export default GenericInputValidation;
現在是 ValidatedInput 欄位的實作:
export const ValidatedInput = (props: ValidatedInputProps) => {
const [errors, setErrors] = useState([...(props.externalErrors || [])]);
const errorMessages = filterMessagesByType(errors, ERROR_TEMPLATES) || [];
const warningMessages = filterMessagesByType(errors, WARNING_TEMPLATES) || [];
let css = '';
if(errorMessages.length !== 0){
css= 'validation-failed'
}else if(warningMessages.length !== 0){
css = 'validation-warning'
}
const DOMprops = getDomProps(props);
registerValidationComponent(props, errorMessages.length > 0 ? errorMessages : warningMessages, setErrors);
return (
<div>
<Input
{...DOMprops}
onBlur={e => {
generateBlur<HTMLInputElement>(props, errors, setErrors)(e);
}}
id={props.id || props.name}
className={css}
key={props.id + errors.length}
readOnly={props.readOnly}
type={props.type}
maxLength={props.maxLength}
/>
{errors.length !== 0 && (
<Tooltip anchorSelect={`#${props.id || props.name}`} place="top">
{getErrorsForTooltip(errors)}
</Tooltip>
)}
</div>
);
};
export default ValidatedInput;
以及導航實作:
const navigate = useNavigate();
const dispatch = useDispatch();
const defaultBack = () => {
navigate(-1);
};
const [warningAcknowledged, setWarningAcknowledged] = useState(false);
const handleBackClick = () => {
dispatch(setWarningsAcknowledged(false));
setWarningAcknowledged(false);
if (props.handleOnBackClick) {
props.handleOnBackClick();
} else {
defaultBack();
}
};
useEffect(() => {
setWarningAcknowledged(false);
}, [JSON.stringify(props.registeredValidations)]);
const nextFunction = async () => {
const foundErrors = [];
for (const registered of Object.values(props.registeredValidations)) {
const { value, validations, customValidations, errors, setErrors } = registered;
const validationProps: ValidationProps = {
name: registered.name,
newValue: value,
validations,
customValidations,
errors,
setErrors,
isOptional: registered.isOptional,
maxLength: registered.maxLength,
};
foundErrors.push(...(await runValidations(validationProps)));
}
const errorMessages = filterMessagesByType(foundErrors, ERROR_TEMPLATES);
const warningMessagesFiltered = filterMessagesByType(foundErrors, WARNING_TEMPLATES);
const infoMessages = filterMessagesByType(foundErrors, INFO_TEMPLATES);
const hintMessages = filterMessagesByType(foundErrors, HINT_TEMPLATES);
const warningMessagesAndInfo = warningMessagesFiltered.concat(infoMessages);
const warningMessages = warningMessagesAndInfo.concat(hintMessages);
if (errorMessages.length > 0) {
return;
} else if (warningMessages.length > 0 && !warningAcknowledged) {
setWarningAcknowledged(true);
return;
}
props.handleOnNextClick();
return (
<Container className="mt-4">
<Row>
<Col xs={6}>
{!props.hideBack && (
<Button name={'zurück' + (props.nameSuffix || '')} id={'back-button' + (props.nameSuffix || '')} onClick={handleBackClick}>
<FontAwesomeIcon icon={faArrowLeft}></FontAwesomeIcon> <Translate contentKey="generic.back" />
</Button>
)}
</Col>
<Col xs={6} className="next-button-col">
{!props.hideNext && (
<Button
name={'weiter' + (props.nameSuffix || '')}
id={'next-button' + (props.nameSuffix || '')}
onClick={() => {
nextFunction();
}}
>
<Translate contentKey="generic.next" /> <FontAwesomeIcon icon={faArrowRight}></FontAwesomeIcon>
</Button>
)}
</Col>
</Row>
</Container>
);
現在當一切完成並在頁面中調用 ValidatedInput,並保存一次值(發生在 onNextClick 時),然後返回到我從請求存儲獲取值的頁面,我在輸入欄中看到的值完全正常。現在當我想刪除輸入(只是為了觸發驗證)並點擊下一步時——驗證被觸發,這是可以的,但欄位中的值返回到舊的值,而不是保留新的並顯示該欄位不正確。
範例:
欄位的值為:"test123" 我將其更改為:"" 點擊下一步按鈕時會觸發驗證,結果不是保持值為 "",而是返回 "test123"
有什麼方法可以修好它嗎?
答案#1
你能建立一個程式碼沙盒來展示你的問題嗎?我猜問題可能來自你修改 formData 的方式,我以前在更改物件屬性時也遇到過類似的問題。也許可以嘗試將 initialState 移到組件外,並用 console.log registered.name 來查看它是否有你需要的數據?目前,我從你的程式碼獲得的信息不多,所以我不確定你是否不小心錯誤地修改或重新指派了它。另外,對於 Input 組件的建議,我認為你應該保持 key 穩定,使用 key={props.id + errors.length} 可能會導致你的組件出現一些不必要的重新渲染。