如何防止每次击键时重新生成验证模式

问题描述 投票:0回答:1

我正在使用

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
)。我希望它仅在第一页加载时生成。我研究了解决方案,但找不到适合我的情况的答案。

如何解决这个问题?有什么建议欢迎欢迎

javascript reactjs react-hooks formik yup
1个回答
0
投票

使用

useMemo
钩子获取验证模式的记忆值。

const memoizedValidationSchema = useMemo(
  () => generateFormikValidationSchema(allEntityProperties),
  [allEntityProperties]
);

这将保证仅在更新

allEntityProperties
时更新验证模式。

将此作为验证模式传递到您的表单。

const formik = useFormik({
  // Other properties
  validationSchema: memoizedValidationSchema,
});

allEntityProperties
本身可能是一个数组,其引用在每次渲染时都会更新。这将使
useMemo
钩子变得无用,并且仍然在每次渲染时生成新的验证模式。在这些情况下,您可以尝试使用 refs 的解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.