首页 > 解决方案 > 用 Formik 反应备忘录

问题描述

我有一个包含很多表单字段的应用程序。我想要一种可以避免重新渲染的方法。我正在使用 Formik 来管理表单。

我正在使用 FormikuseField来访问我的子组件中的 Formik 表单值,因为React.memo只是进行了浅比较。我想为备忘录方法写一个自定义回调

function MainForm3() {
  const initialValues = { txtArea: "" };
  return (
    <Formik initialValues={initialValues}>
      {(formik) => {
        return (
          <>
            <TextArea
              name={"txtArea"}
              rows={3}
              id={"txtArea"}
              label={"txtArea"}
            />
          </>
        );
      }}
    </Formik>
  );
}

function TextArea(props: any) {
  const [field] = useField(props);

  return <TextField {...field} />;
}

React.memo(TextArea, (prev, next) => {
  //how do i get access to the formik to perform a comparison
});

由于 prev 和 next 值只能访问传递的直接属性,因此我无法比较 memo 函数中的 Formik 字段值。

要获得 Formik 字段的处理程序,我需要使用 a useField,但这在回调中不起作用,因为它说 Hooks 不能在非 React 方法中使用。

由于我有一个复杂的表单,我需要一个处理程序来在允许渲染之前执行实际的深度比较。

我不想使用 Fastfield,因为它的内部比较同样肤浅。

我正在使用 React 16.13 和 Formik 2.1.5

标签: javascriptreactjsperformanceformik

解决方案


Formik 在后台使用 React 上下文。这会产生额外重新渲染的问题。看看文章
在您的场景中,简单地添加memoization 是行不通的,<Formik>只要 Formik 的值发生变化,所有嵌套的组件都将被重新渲染。相反,您可以尝试使用withFormik hoc,它不使用引擎盖下的反应上下文,因此添加 React.memo 将起作用。 

几天前我不得不处理同样的问题,我发现useFormik, useField,useFormikContext会导致所有嵌套组件重新渲染,所以请避免使用这些钩子。如果您需要使用 onChange、onBlur、setFieldValue、errors 或 touch - 将它们作为道具传递给您的输入。


推荐阅读