🚅

Next.js + Material UIで文字とアイコンによるリンクを作成

2022/02/12に公開約2,100字

概要

Next.jsには備えつけのLinkコンポーネントがあります。
個人開発をしていて、「アイコンと文字がchildとしてどっちもあるリンクを作ろう!」と思い、Next.jsのLinkにてそれをしようと思ったのですが、エラーを吐かれてしまい困りました。

どんなエラー?

こんなエラーです。

Error: Multiple children were passed to <Link> with `href` of `/` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children

かいつまむと、「複数のchildがLinkに渡されているが、サポートされているchildの数は1つだよ」と言われているようです。

その時点ではこのようにして書いていました。
CreateはMaterial UIの鉛筆アイコンです。

import Link from "next/link"
import { Create } from "@mui/icons-material"

<Link href="/">
  <a>記事を書く</a>
  <Create />
</Link>

「記事を書く」というaタグと、鉛筆アイコンは別のものなのだから、どうやってもchildは2つになるのでは?と思い困っていました。

解決策

ただ調べていると、以下のようにするとやりたいことが実現できるのがわかりました。

import MuiLink from "@mui/material/Link"
import NextLink from "next/link"

<NextLink href="/edit" passHref>
  <MuiLink
    underline="none"
    css={css`
      color: black;
      text-decoration: none;
      display: flex;
      align-items: center;
    `}
  >
    記事を書く
    <Create />
  </MuiLink>
</NextLink>

かんたんに解説します。

LinkコンポーネントはNext.jsとMaterial UIのどちらともからimportしてきて、それぞれNextLink, MuiLinkと名付けます。

使用の際はNextLinkでMuiLinkをラップして、NextLinkのhrefで遷移先を指定、およびpassHrefをセットして、MuiLinkに遷移先のデータを渡してあげます。

イメージとしては、普段Next.jsでLinkを使う際にchildとして入れているaタグがMuiLinkになった感じです。

NextLinkはMuiLinkという一つのchildしか持っていないため、ちゃんと条件を満たしており、かつMuiLinkでは複数のchildを持つことが許容されているので、この形によってやりたいことが実現できるというわけです。

ちなみに実際のページ遷移の処理はNext.js側のLinkが作動しています。

また、生の状態だと文字とアイコンの高さの配置がずれてしまうので、文字色などと併せてcssで整えています。

完成形の見た目は以下になります。



やったね!

ちなみに

私はNext.js初心者なので、「Material UIのLinkは複数のchildを許容してくれるなら、初めからそっちだけ使えばいいのでは?」と少し悪いことを考えたりもしました。

しかし結論を言うと、そうするとNext.js特有の、クライアントサイドでのページ遷移が使えなくなるので、本来なら出せたスピードを出すことができず、結果的にサイトのパフォーマンスを部分的に下げる可能性があります。

実際にMaterial UIのLinkとNext.jsのLinkの遷移速度を比べてみたところ、遷移先が軽いページだとあまり速さは変わりませんでしたが、重いコンポーネントを持ったページだと結構な時間ちがいました。

なので、Next.js環境でLink内で文字とアイコンを併存させたいときは、この方法をおすすめします👌

(そもそもNext.jsを使っている以上、Routingや遷移などで備えつけのコンポーネントを使わないのは、おそらくナンセンスなのでしょう)

参考記事

https://maku.blog/p/vgs4dnw/

Discussion

ログインするとコメントできます