Chakra UI × Next.js でButtonをLinkとして使う時の注意(isDisabled編
サンプルはコチラ
以下の解説と合わせて動作確認にご利用ください
TL;DR
aタグとしてレンダリングされるButtonコンポーネントは、isDisabledを指定してもクリックで飛べちゃうので注意。
hrefを省略すると良いです。
ただしNextLinkと絡めて使う場合は省略できないので、工夫が必要です。
Chakra UI を使う場合、通常ボタンはこういう書き方をしますよね。
そして isDisabled=true
にするとボタンが非活性になり、押しても何も起こらないのが期待値です。
<Button colorScheme="blue">通常のボタン</Button>
<Button colorScheme="blue" isDisabled>
通常のボタン
</Button>
このボタンをリンクとして動作させたい場合、 as="a"
のようにするとaタグとしてレンダリングされます。
そして href="/path"
とすると指定されたページに遷移します。
このとき isDisabled=true
を指定するとどのような挙動になりますか?
押しても何も起こらないのがみなさんの期待値だと思います。
<Button
as="a"
href={externalLink}
target="_blank"
rel="noopener noreferrer"
colorScheme="blue"
isDisabled
>
間違ったリンクボタン
</Button>
(「間違ったリンクボタン」がネタバレ感ありますが。。。)
見た目はボタンが非活性となりますが、クリックすることでページ遷移が発生します。
ではどのようにすれば良いでしょう?
以下の ExternalLinkButton
のコンポーネントのように対応してみます。
const ExternalLinkButton = (props: ComponentProps<typeof Button>) => {
const { isDisabled, href } = props;
return (
<Button
as="a"
target="_blank"
rel="noopener noreferrer"
{...props}
href={isDisabled ? undefined : href}
/>
);
};
hrefを省略することでページ遷移が起こらないようになりました。
これで期待値どおりの挙動になりますね。
※ExternalLinkButton: 外部サイトへのリンク時には後述の next/link
を使わないのでこの命名にしています
※hrefの省略についてFYI:https://github.com/chakra-ui/chakra-ui/issues/2255#issuecomment-712927834
Next.jsの next/link
には同一サイト内のリンクをprefetchしてくれるなどroutingに関するいくつかの機能があります。
これをChakra UIと併用する場合はNextLink として扱います。
Buttonコンポーネントを next/link
として使用するためには as="NextLink "
を指定します。
このときisDisabledを指定するとどのような挙動になるでしょう?
<Button as={NextLink} href="/" colorScheme="blue" isDisabled>
間違ったNextLinkボタン
</Button>
ここでもやはりボタンが非活性となりますが、クリックすることでページ遷移が発生します。
そのためhrefを省略したくなるのですが、NextLinkはhrefが必須パラメータなので省略できません。
ではどのようにすれば良いでしょうか?
以下の NextLinkButton のコンポーネントのように対応してみます。
const NextLinkButton = (props: ComponentProps<typeof Button>) => {
const { isDisabled } = props;
if (isDisabled) {
return <Button as="a" {...props} href={undefined} />;
}
return <Button as={NextLink} {...props} />;
};
isDisabledでないときはNextLinkを返しています。
isDisabledのときはNextLinkを使わず、ExternalLinkButtonと同様にhrefを省略して返す様にしました。
こうすることでページ遷移が起こらないようになり、期待通りの挙動になりますね。
いかがだったでしょうか?
もしかするとNextLinkの解決法について、より良い方法があるかもしれません。
もしこの例とは異なる解決法を取られてる方がいれば是非教えて下さい!