Jak wyeksportować forwardRef z ForwardRefRenderFunction

Oct 06 2020

Mam składnik, który należy do biblioteki interfejsu użytkownika, nazwijmy go komponentem wejściowym. Korzystając z tej biblioteki do wywoływania Input, istnieje wiele typów, które mogę wywołać. Na przykład

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

Teraz chcę napisać opakowanie do tego komponentu wejściowego, więc piszę w ten sposób

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;

w index.tsx

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

Następnie mogę ich używać w ten sposób:

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

Ale robiąc to, nie mogę użyć metod ref z oryginalnej biblioteki UI (coś w rodzaju inputRef.current.focus()). Dlatego używam forwardRef i ForwardRefRenderFunction tak

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);

Zmieniając się na to, mogę przekazać ref do oryginalnej biblioteki interfejsu użytkownika i mogę używać jej oryginalnych metod. Jednak mój problem teraz jest, kiedy zmieni się forwardRef i ForwardRefRenderFunction , nie mogę nazwać TextArea i Szukaj więcej

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

To jest błąd:

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.

Czy ktoś może mi w tym pomóc? Dzięki

Odpowiedzi

1 PeterLehnhardt Oct 07 2020 at 07:23

To, co robisz, to:

  1. Zdefiniuj funkcję InputWrapperjako typInputWrapperComponent
  2. Zdefiniuj Searchi TextAreajako członkówInputWrapper
  3. Utwórz komponent przekierowania referencji z forwardRef

Problem w tym, że forwardReftworzy zupełnie nowy komponent i nie dba o to, czy wcześniej zdefiniowano jakieś podkomponenty. Zostaną po prostu wyrzucone, a ty otrzymasz błąd, że członkowie są niezdefiniowani.

Tak więc droga do zrobienia jest właściwie:

  1. Zdefiniuj funkcję InputWrapperjako typInputWrapperComponent
  2. Utwórz komponent przekierowania referencji z forwardRef
  3. Zdefiniuj Searchi TextAreajako członków nowego składnika przekazywania referencji
1 JakeLam Oct 07 2020 at 05:32

W końcu używam ForwardRefExoticComponent zamiast ForwardRefRenderFunction

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

Ale naprawdę nie jestem pewien, jaka jest różnica między nimi

Aktualizacja : Sprawdź odpowiedź Piotra.

Jaka jest różnica między tymi dwoma, sprawdź jego odpowiedź tutaj: Jaka jest różnica między ForwardRefExoticComponent i ForwardRefRenderFunction w reagowaniu?