Как экспортировать forwardRef с помощью ForwardRefRenderFunction

Oct 06 2020

У меня есть компонент, который принадлежит библиотеке пользовательского интерфейса, позвольте называть его компонентом ввода. При использовании этой библиотеки для вызова Input я могу вызывать много типов. Например

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

Теперь я хочу написать оболочку для этого компонента ввода, поэтому я пишу вот так

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;

в index.tsx

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

Тогда я могу использовать их так:

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

Но делая это, я не могу использовать методы ref из исходной библиотеки пользовательского интерфейса (что-то вроде inputRef.current.focus()). вот почему я использую forwardRef и ForwardRefRenderFunction вот так

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

Сделав это, я могу передать ссылку в исходную библиотеку пользовательского интерфейса и использовать ее оригинальные методы. Тем не менее, моя проблема сейчас, когда я изменяю forwardRef и ForwardRefRenderFunction , я не могу назвать TextArea и Поиск больше

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

Это ошибка:

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.

Кто-нибудь может дать мне какое-то руководство по этому поводу? благодаря

Ответы

1 PeterLehnhardt Oct 07 2020 at 07:23

Что вы делаете:

  1. Определите функцию InputWrapperкак типInputWrapperComponent
  2. Определить Searchи в TextAreaкачестве членовInputWrapper
  3. Создайте компонент пересылки ссылок с forwardRef

Проблема в том, что это forwardRefсоздает совершенно новый компонент и не заботится о том, были ли ранее определенные подкомпоненты. Они будут просто выброшены, и вы получите ошибку, что эти члены не определены.

Итак, путь на самом деле следующий:

  1. Определите функцию InputWrapperкак типInputWrapperComponent
  2. Создайте компонент пересылки ссылок с forwardRef
  3. Определите Searchи в TextAreaкачестве членов нового компонента пересылки ссылок
1 JakeLam Oct 07 2020 at 05:32

В итоге я использую ForwardRefExoticComponent вместо ForwardRefRenderFunction.

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

Но я действительно не уверен, в чем разница между ними

Обновление : проверьте ответ Питера.

В чем разница между ними, проверьте его ответ здесь: В чем разница между ForwardRefExoticComponent и ForwardRefRenderFunction в реакции?