Как мне обернуть компонент intrinsi c, сохранив большую часть реквизита? - PullRequest
1 голос
/ 25 апреля 2020

Я хочу обернуть стандартную кнопку своим собственным функциональным компонентом React, но я хочу, чтобы пользователь нового компонента мог установить почти все реквизиты базовой кнопки. Конечно, я хочу сохранить правильную типизацию, поэтому, если WrappedButton заключает в себе button,

<WrappedButton formNoValidate={true} onClick={handleClick} />

будет компилироваться правильно, но

<WrappedButton formNoValidate={5} onKrapnik={handleClick} />

не будет, так как formNoValidate набирается как логическое значение, а onKrapnik не существует.

Очевидно, я не хочу составлять исчерпывающий (и fr agile) список юридических реквизитов базового компонента.

1 Ответ

0 голосов
/ 25 апреля 2020

Исходный компонент имеет некоторое количество реквизита. Для каждого реквизита вы можете

  • пропустить его через нетронутым
  • изменить каким-либо образом
  • опустить его
  • изменить его тип

Вы также можете добавить свои собственные реквизиты. Давайте рассмотрим простой случай, вы просто хотите добавить новые реквизиты. Я делаю кнопку нового типа под названием MultiClick, в которую добавляется дополнительная опора:

type MultiClickProps = {
  clickCount?: number;
} & JSX.IntrinsicElements["button"];

const MultiClick: React.FC<MultiClickProps> = ({
  clickCount = 2,
  ...buttonProps
}) => {
// do some stuff
  return (
    <button {...buttonProps} />
  );
};

Конечно, это не очень полезно: как "некоторые вещи" могут сделать что-то значимое, если конец В результате вы должны вернуть кнопку со всеми реквизитами, пропущенными без изменений?

Таким образом, вы можете перехватить и изменить некоторые реквизиты:

const MultiClick: React.FC<MultiClickProps> = ({
  clickCount = 2,
  onClick,
  ...buttonProps
}) => {
  const handleClick = (
    event: React.MouseEvent<HTMLButtonElement, MouseEvent>
  ) => {
    // do some stuff
    onClick(event);
  };

  return (
    <button {...buttonProps} onClick={handleClick}/>
  );
};

Таким образом, есть возможность реально взаимодействовать с действиями обернутого компонента.

Теперь предположим, что вам не нравится аргумент «event» в onClick и вы хотите заменить что-то еще, число. Чтобы изменить тип, вы фактически должны опустить старую опору и переписать ее, например, так:

type MultiClickProps = {
  clickCount?: number;
  onClick: (n: number) => void;
} & Omit<JSX.IntrinsicElements["button"], 'onClick'>;

Вы можете увидеть готовый код здесь .

Кстати, все это зависит от существования JSX.IntrinsicElements, которые сотрудники React были любезны предоставить. Предположим, вы пытаетесь обернуть функциональный компонент из некоторой библиотеки, которая не экспортировала аккуратный тип реквизита?

К счастью, вы можете сгенерировать свой собственный тип реквизита для любого функционального компонента, написанного на Typescript, с этим:

type PropsOf<T> =
    T extends React.FunctionComponent<infer U> ? U : never;

, который при применении к вышеуказанной функции, например, так:

type MultiClickProps = PropsOf<typeof MultiClick>;

будет оцениваться как

type MultiClickProps = {
    clickCount?: number;
} & React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement>
...