簡體   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