如何在样式组件v4 + TypeScript中使用prop值设置属性?

时间:2019-04-30 00:20:11

标签: javascript reactjs typescript styled-components

摘要

给出:

const Link = styled.a`
  border: solid 1px black;
  border-radius: 5px;
  padding: 5px;
  margin: 10px 5px;
`;

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;
const LinkAsButton = styled(Link).attrs<ButtonProps>
>(({
  as: 'button',
  className: 'btn btn-primary'
})`
  border: solid 1px red;
`;

如何将按钮专用道具(例如已禁用)传递给LinkAsButton

回购(包括v3和v4的分支)表明存在问题:https://github.com/arteforme/v3-v4-styled-components-migration

版本3

在v3中,我可以执行以下操作:

package.json

"dependencies": {
    "@types/react": "^16.8.8",
    "@types/react-dom": "^16.8.2",
    "react": "^16.8.4",
    "react-dom": "^16.8.4",
    "react-scripts": "2.1.8",
    "styled-components": "^3.3.3",
    "typescript": "^3.3.3333"
  }

组件定义

type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;

const Link = styled.a`
  border: solid 1px black;
  border-radius: 5px;
  padding: 5px;
  margin: 10px 5px;
`;

const LinkAsButton = Link.withComponent('button')
  .extend.attrs<ButtonProps>({
  className: 'btn btn-primary'
})`
  border: solid 1px red;
`;

,在使用代码中,我可以在LinkAsButton组件上指定按钮专用的道具(例如,禁用,表单等)。

版本4

在v4中,我希望达到相同的效果;但是,我没有成功确定如何去做。根据最新文档,我已将LinkAsButton更新为不再调用extendwithComponent,而是将Link包装在对styled的调用中并使用{{ 1}}来指定标签。 v4版本如下:

package.json

as

组件定义

dependencies": {
    "@types/react": "^16.8.14",
    "@types/styled-components": "^4.1.14",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-scripts": "2.1.8",
    "styled-components": "^4.2.0",
    "typescript": "^3.4.5"
  }

并且在使用代码中,我在const LinkAsButton = styled(Link).attrs<ButtonProps> >(({ as: 'button', className: 'btn btn-primary' })` border: solid 1px red; `; 实例上指定了disabled={true},但是无法编译。而是,出现以下错误:

属性'disabled'在类型'IntrinsicAttributes&Pick,HTMLAnchorElement>,“ type”中不存在| “ defaultChecked” | “ defaultValue” | “ suppressContentEditableWarning” | ... 257更多... | “ referrerPolicy”>&{...; },“类型” | ... 261更多... | “ referrerPolicy”>&Partial <...>,“类型” | ....'。 TS2322

查看属性定义

看一下定义文件,我注意到可以指定两个通用参数。

LinkAsButton

据我所知,attrs < U, NewA extends Partial<StyledComponentPropsWithRef<C> & U> & { [others: string]: any; } = {} > ( attrs: Attrs<StyledComponentPropsWithRef<C> & U, NewA, T> ): ThemedStyledFunction<C, T, O & NewA, A | keyof NewA>; 是包装的组件,我相信C是NewAttributes。在这种情况下,我无法确定U是什么,但是我尝试指定第二个通用参数。

NewA

这样做会导致以下错误:

类型'ButtonHTMLAttributes'不能分配给类型'Partial,HTMLAnchorElement>,“ type” | “ defaultChecked” | “ defaultValue” | “ suppressContentEditableWarning” | ... 257更多... | “ referrerPolicy”>&{...; }和ButtonHTMLAttributes <... >>'。     属性“ onCopy”的类型不兼容。

掌握这些信息后,我会尝试:

const LinkAsButton = styled(AnchorLink).attrs<{}, ButtonProps>`
  // omitted for brevity
`

现在可以在标记中指定const LinkAsButton = styled(Link).attrs< {}, { as: string; className: string; disabled?: boolean } >({ as: 'button', className: 'btn btn-primary' })``; ,但不能指定其他按钮专用道具(例如disabled

非理想解决方案

一种方法是执行以下操作:

form

消费代码:

const LinkAsButton = styled(Link)<ButtonProps>`
  border: solid 1px red;
`;

但是,这将导致很多代码重复:(。

1 个答案:

答案 0 :(得分:0)

通过在调用.attrs之后移动通用参数来使其正常工作。

const LinkAsButton = styled(Link).attrs
>(({
  as: 'button',
  className: 'btn btn-primary'
})<ButtonProps>`
  border: solid 1px red;
`;

现在可以在JSX中设置ButtonProps中定义的任何道具