我正在使用
Formik
的 useFormik()
来跟踪我的表单状态,并使用 Yup
进行验证。我的一些表单字段是相互依赖的。在我的用例中,我需要动态生成验证模式。以下是我的代码的相关部分:
// main view where I create formik and validation schema
const EntityView = (props) => {
const formik = useFormik({
initialValues: {
properties: [
// ... array of objects describing form fields
// and validation patterns
]
// ...
},
onSubmit: () => { },
// notice! dynamically generated schema
validationSchema: generateFormikValidationSchema(allEntityProperties),
validateOnChange: true,
})
return (
<div className="space-y-20">
{formik.values.properties.map(property => {
switch (property.type) {
case "number":
return <Input name={property.name}
value={/* assosiated formik value*/}
onChange={formik.handleChange}
...
/>
case "textarea":
return <Textarea name={property.name}
value={/* assosiated formik value*/}
onChange={formik.handleChange}
...
/>
}
})}
</div>
)
}
这就是我动态生成验证模式的方式:
const generateFormikValidationSchema = properties => {
console.log(" regenerating ...") // ! <---------- HERE
const shape = {}
properties.forEach(prop => {
if (prop.details.is_required) {
switch (prop.details.type) {
case "number":
shape[prop.id] = yup.number()
.min(1, "must be greater than 1")
.max(49, "must be less than 50")
.required("majburiy maydon")
.when(["a"], (reliantProp, schema) => {
let newRule = undefined
// code emitted for simplicity
switch (otherFieldValue) {
...
}
return newRule
})
break
case "textarea":
...
}
}
})
return yup.object().shape({ properties: yup.object(shape) })
}
如您所见,我创建了一个 formik 实例一次,并将 formik 的值和处理函数传递给子组件。
一切工作正常(包括相互依赖的验证、formik 的状态)。我的问题是每次击键时我的验证模式都会重新生成(调用
generateFormikValidationSchema
)。我希望它仅在第一页加载时生成。我研究了解决方案,但找不到适合我的情况的答案。
如何解决这个问题?有什么建议欢迎欢迎
使用
useMemo
钩子获取验证模式的记忆值。
const memoizedValidationSchema = useMemo(
() => generateFormikValidationSchema(allEntityProperties),
[allEntityProperties]
);
这将保证仅在更新
allEntityProperties
时更新验证模式。
将此作为验证模式传递到您的表单。
const formik = useFormik({
// Other properties
validationSchema: memoizedValidationSchema,
});
allEntityProperties
本身可能是一个数组,其引用在每次渲染时都会更新。这将使 useMemo
钩子变得无用,并且仍然在每次渲染时生成新的验证模式。在这些情况下,您可以尝试使用 refs 的解决方法。