Como exportar forwardRef com ForwardRefRenderFunction

Oct 06 2020

Estou tendo um componente que pertence a uma biblioteca de interface do usuário, vamos chamá-lo de componente de entrada. Ao usar esta biblioteca para chamar Input, há muitos tipos que posso chamar. Por exemplo

<Input />
<Input.TextArea />
<Input.Search />

Agora eu quero escrever um wrapper para este componente de entrada, então escrevo assim

type InputWrapperComponent = FC<InputProps> & {
  Search: typeof Input.Search;
  TextArea: typeof Input.TextArea;
};

const InputWrapper: InputWrapperComponent = (props) => {
  // make some minor changes here
}

InputWrapper.Search = Input.Search;
InputWrapper.TextArea = Input.TextArea;
export default InputWrapper;

em index.tsx

export { default as InputWrapper } from './input';

Então posso usá-los assim:

<InputWrapper />. --> Works
<InputWrapper.TextArea />. --> Works
<InputWrapper.Search />. --> Works

Mas, ao fazer isso, não posso usar métodos ref da biblioteca UI original (algo como inputRef.current.focus()). é por isso que eu uso forwardRef e ForwardRefRenderFunction assim

type InputWrapperComponent = ForwardRefRenderFunction<HTMLInputElement, InputProps> & {
  Search: typeof Input.Search;
  TextArea: typeof Input.TextArea;
};

const InputWrapper: InputWrapperComponent = (props, ref) => {
  // make some minor changes here and add the ref to the input
}

InputWrapper.Search = Input.Search;
InputWrapper.TextArea = Input.TextArea;
export default forwardRef(InputWrapper);

Ao mudar para isso, posso passar o ref para a biblioteca de interface do usuário original e usar seus métodos originais. No entanto, o meu problema agora é quando eu mudar para forwardRef e ForwardRefRenderFunction , eu não posso chamar TextArea e Pesquisar mais

<InputWrapper />. --> Works
<InputWrapper.TextArea />. --> Error
<InputWrapper.Search />. --> Error

Este é o erro:

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Alguém pode me dar alguma orientação sobre isso? obrigado

Respostas

1 PeterLehnhardt Oct 07 2020 at 07:23

O que você está fazendo é:

  1. Definir função InputWrappercomo tipoInputWrapperComponent
  2. Definir Searche TextAreacomo membros deInputWrapper
  3. Crie um componente de encaminhamento de referência com forwardRef

O problema é que isso forwardRefcria um componente completamente novo e não se importa se houve alguns subcomponentes definidos antes. Eles serão jogados fora e você terá o erro de esses membros serem indefinidos.

Portanto, o caminho a seguir é:

  1. Definir função InputWrappercomo tipoInputWrapperComponent
  2. Crie um componente de encaminhamento de referência com forwardRef
  3. Definir Searche TextAreacomo membros do novo componente de encaminhamento de referência
1 JakeLam Oct 07 2020 at 05:32

Acabo usando ForwardRefExoticComponent em vez de ForwardRefRenderFunction

type InputWrapperComponent = React.ForwardRefExoticComponent<
  React.PropsWithoutRef<InputProps> & React.RefAttributes<HTMLInputElement>
> & {
  Search: typeof Input.Search;
  TextArea: typeof Input.TextArea;
  Password: typeof Input.Password;
};

Mas eu realmente não tenho certeza qual é a diferença entre eles

Atualização : verifique a resposta de Peter.

Para qual é a diferença entre os dois, verifique sua resposta aqui: Qual é a diferença entre ForwardRefExoticComponent e ForwardRefRenderFunction em react?