繁体   English   中英

react-hook-form FormProvider 与受控组件的性能(或者,如何记忆受控组件)

[英]react-hook-form FormProvider performance with controlled components (or, how to memoize controlled components)

我正在使用FormProvider来处理动态创建的“深度嵌套”表单。 FormProvider 性能文档说,“...[FormProvider] 还会导致组件树在 React Hook Form 触发 state 更新时触发重新渲染”,并建议记忆组件来解决这个问题。 我正在使用受控组件 (MUI),但不知道如何进行记忆。 这是返回表单输入控件的深层嵌套部分:

const FormContent = ( {content} ) => { 
  return content.map((item, i) => { 
    const name = item.component.props.name;

    return ( 
      <ConnectForm key={name + '_' + i}>
        {() => <Controller
          name={name}
          defaultValue=''
          render={({ field: { onChange, onBlur, value, name, ref },
                     fieldState: { error },
                     formState: { isDirty } }) => { 
              return React.cloneElement(item.component, { 
                name: name,
                value: value,
                onChange: onChange,
                inputRef: ref,
                error: isDirty && !!error,
                helperText: isDirty && error?.message,
                FormHelperTextProps: { error: true } 
              })
            } 
          } 
        />}
      </ConnectForm>
    );
  });
}

我试着做

  render={ 
    memo(({ field: { onChange, onBlur, value, name, ref },
      return React.cloneElement(item.component, { 
        ...
      })
    },
    (prevProps, nextProps) =>
      prevProps.formState.isDirty === nextProps.formState.isDirty)
  } 

Controller会引发 TypeDef 错误,即“props.render 不是函数”。 如果我做

{() => memo(<Controller
  ...
/>,
(prevProps, nextProps) =>
  prevProps.formState.isDirty === nextProps.formState.isDirty
)}

或者

  memo(<ConnectForm key={name + '_' + i}>
    {() => <Controller
      ... 
    />}
  </ConnectForm>,
    (prevProps, nextProps) =>
      prevProps.formState.isDirty === nextProps.formState.isDirty
  )

它警告memo “第一个参数必须是一个组件。而不是接收:对象”,并且ConnectForm (或第二个实例中的FormContent )抛出一个错误,“对象作为 React 子项无效”。

我如何使用受控组件实现这种“性能增强”?

嘿,不确定您是否仍然遇到此问题,但我已经构建了一个新的表单库,它没有任何这些问题。 您可以拥有嵌套组件而无需执行任何特殊操作。

它处于测试阶段,目前正在开发中,但它可能会解决您遇到的问题。

如果您愿意,可以在这里查看: https://react-formz.zerry.dev/docs/intro/

import {
  Form,
  TextField,
  NumberField,
  DependentTextField,
} from "@zerry/react-formz";

const NestedInput = () => {
  return (
    <TextField
        required
        name="name"
        as={({ input }) => <input {...input} />}
    />
  )
}

const MyForm = () => {
  return (
    <Form initialValues={{ name: "", age: "" }}>
      <NestedInput />
      <NumberField
        required
        name="age"
        as={({ input }) => <input {...input} />}
      />
    </Form>
  );
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM