背景
最近バイト先のプロダクトを、Next.jsをTypescriptでやりつつUIはMaterial-UIでよしなにするという技術スタックでやっています。
困ったこと
Material-UIのCard
を配置してその中のCardActions
のchildrenとしてNextのLink
を渡したらLink: unknown props found: className
と言われました。
原因
CardActions
のchildrenには自動的にclassName
が振られるらしい。しかし、NextのLink
にclassName
を渡すと、上記の警告が出てしまう、ということらしい。
解決策
propsとして渡されたclassName
をLink
ではなくLink
の中のアンカーに渡してやるようなコンポーネントを作ってしまえばいい。今回の場合はMaterial-UIなので、そのアンカーはButton
コンポーネントです。LinkのchildrenとButtonのhrefはこの場合は不要なので、Omitで省きます。
import React from 'react'
import { Button } from '@material-ui/core'
import { ButtonProps } from '@material-ui/core/Button'
import Link, { LinkState } from 'next/link'
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
interface ButtonLinkProps {
linkProps: Omit<LinkState, 'children'>
buttonProps: Omit<ButtonProps, 'href'>
className?: string
}
const ButtonLink: React.SFC<ButtonLinkProps> = ({ linkProps, buttonProps, className, children }) => (
<Link {...linkProps} passHref>
<Button className={className} {...buttonProps}>
{children}
</Button>
</Link>
)
export default ButtonLink
追記
これをやったあと、CTOから、「linkProps
、buttonProps
わけずに普通に渡せるようにしたいっすね」と言われたので、変更です。
import React from 'react'
import { Button } from '@material-ui/core'
import { ButtonProps } from '@material-ui/core/Button'
import Link, { LinkState } from 'next/link'
type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
type ButtonLinkProps = Omit<ButtonProps, 'href'> & Omit<LinkState, 'children' | 'passHref'> & {
className?: string
}
const ButtonLink: React.SFC<ButtonLinkProps> = ({
href,
as,
prefetch,
shallow,
scroll,
replace,
className,
children,
...otherProps
}) => (
<Link href={href} as={as} prefetch={prefetch} shallow={shallow} scroll={scroll} replace={replace} passHref>
<Button className={className} {...otherProps}>
{children}
</Button>
</Link>
)
export default ButtonLink
最後に
もっといいやり方あったら教えて、、、