如何封装一个固有组件,保留大部分的道具?

问题描述 投票:1回答:1

我想用自己的React功能组件封装一个标准的按钮,但我希望新组件的用户能够设置几乎所有底层按钮的道具。当然,我希望保持正确的输入方式,所以如果WrappedButton封装了一个 button那么

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

会正确编译,但

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

不会,既因为 formNoValidate 类型为布尔型,并且 onKrapnik 不存在。

很明显,我不想把底层组件的合法道具做一个详尽的(且脆弱的)列表。

reactjs typescript typescript-typings
1个回答
0
投票

原组件有一些道具。 对于每个道具,你可能要

  • 完璧归赵
  • 变通
  • 省略
  • 改型

你也可能想添加一些自己的新道具。我们举个简单的例子,你只是想添加一些新的道具。我正在做一种新的按钮,叫做 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}/>
  );
};

这样一来,就有机会与封装组件的动作进行实际交互。

现在假设你不喜欢onClick的 "event "参数,想用别的东西代替,一个数字。 要改变一个类型,实际上你必须省略旧的道具并重新编写它,就像这样。

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>
© www.soinside.com 2019 - 2024. All rights reserved.