我在表达问题时遇到了麻烦,希望我能在这里对此做足够的解释!
我正在制作一个通用的表单组件,该组件在顶层处理表单验证。最终结果将如下所示:
<Form action='/api/endpoint'>
... form inputs go here
</Form>
一切正常。如果我仔细填写表格,可以很好地提交并进行验证。
表单的状态如下:
{
values: { name: 'Johnny', age: 18, email: 'email@example.com' },
used: { name: true, age: true, email: true },
validators: { name: (Yup Validator), age: (Yup Validator), email: (Yup Validator) }
}
在每个组件中使用自定义onChange和onBlur函数填充状态(它们使用react上下文传递)。例如,对于当前元素,状态的used
部分的onBlur更新为true
,状态的values
部分的onChange更新为元素值,等等。
如上所述,这在我遍历并使用每个元素时都很好用。我想发生的是,当用户单击Submit
按钮时,它将在发送POST请求之前检查 EVERY 字段以确保其有效。
我想做的一个简单解决方案是仅以编程方式模糊每个调用onBlur函数的元素。但是,由于setState是异步的,因此它只会将最后一个元素添加到状态中(因为这样有意义,因为它会被覆盖)。
我想知道是否可以修改设置表单状态的方式或是否可以在重新设置表单状态之前等待。
我正在使用功能组件,并且我知道useEffect可以用于此目的,但是我不确定如何在我的情况下使用它。
这是我设置状态onChange和onBlur的方式:
const handleBlur = (e) => {
e.persist();
setFormState({...formState, used: {...formState.used, [e.target.name]: true}});
}
(希望您可以从中推断出onChange,它是相同的,只是用values
而不是used
)
我模糊所有内容的想法如下:
const blurAll = async () => {
let inputs = [];
// Get all inputs on the current page
const inputTags = document.getElementsByTagName("input");
// Get all text areas (because they are <textarea> instead of <input>)
const textAreas = document.getElementsByTagName("textarea");
// Concat the arrays
inputs.push(...inputTags, ...textAreas);
// Trigger a blur event for each (to initialize them in formstate)
inputs.map(input => { input.focus(); input.blur(); });
}
但是,因为setFormState使用现有的表单状态,所以发生的太快了,因此仅将最后一个元素添加到状态中。
我知道这个blurAll可能不是一个很好的解决方案,但是我只是想使某些东西起作用(然后我将只获取表单本身的输入)。
这使我想到一个问题,如何在重新设置状态之前(在我的onChange和onBlur上)等待上一个setState完成?
或者JavaScript中有没有一种方法可以简单地更新状态对象中的一个键而不是替换整个对象?
如果您需要更多信息,请发表评论,我会尽力提供。我宁愿不使用表单库,而是尝试学习React,这对于增进我的知识似乎是一件好事!谢谢!