1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js LinkとMaterial-UIのMenuItemの型定義互換性問題でハマった話

Posted at

Next.js LinkとMaterial-UIのMenuItemの型定義互換性問題でハマった話

想定読者

  • Next.jsでの開発を始めたばかりの方
  • Material-UIを使い始めた方
  • Webアプリケーション開発初学者

結論から

Next.jsとMaterial-UIの型定義の互換性問題によるエラーが発生する。
UrlObjectを用いた型定義を適切に用いる・NextLinkでMenuItemをラップすることで解決可能である。

開発環境

  • Next.js: 14.2.11
  • Material UI: 6.1.0
  • TypeScript: 5.0

問題のあるコード

最初に、以下のようにMenuItemNextLinkを直接組み合わせようとすると型エラーが発生する:

interface MobileMenuProps {
    menuItems: Array<{
        href: string;
        label: string;
    }>;
}

export function MobileMenu({ menuItems }: MobileMenuProps) {
    return (
        <>
            {menuItems.map((item) => (
                <MenuItem 
                    key={item.href} 
                    component={NextLink} 
                    href={item.href} 
                    onClick={handleClose}
                >
                    {item.label}
                </MenuItem>
            ))}
        </>
    );
}

発生するエラー

No overload matches this call.
Type '{ children: string; key: string; component: <RouteType>(props: LinkProps<RouteType>) => Element; href: string; onClick: () => void; }' 
is not assignable to type 'IntrinsicAttributes & { href: string; } & MenuItemOwnProps & Omit<ButtonBaseOwnProps, "classes"> & CommonProps & Omit<...>'.
Property 'component' does not exist on type 'IntrinsicAttributes & { href: string; } & MenuItemOwnProps...'

解決方法

問題を解決するために以下の2つを行なった:

  1. hrefの型をstringからUrlObjectに変更
  2. コンポーネントの構造を変更し、NextLinkMenuItemをラップする
import { MenuItem } from "@mui/material";
import NextLink from "next/link";
import { UrlObject } from "url";

interface MobileMenuProps {
    menuItems: {
        href: UrlObject;
        label: string;
    }[];
}

export function MobileMenu({ menuItems }: MobileMenuProps) {
    return (
        <>
            {menuItems.map((item) => (
                <NextLink 
                    passHref 
                    href={item.href} 
                    key={item.label} 
                    style={{ textDecoration: "none", color: "inherit" }}
                >
                    <MenuItem onClick={handleClose}>
                        {item.label}
                    </MenuItem>
                </NextLink>
            ))}
        </>
    );
}

変更点について

  1. 型定義の変更

    • hrefの型をstringからUrlObjectに変更することで、Next.jsの型システムとより適切に連携
    • UrlObjectは Next.js の Link コンポーネントが期待する型定義であるためNext.js側の問題を解決
  2. コンポーネント構造の変更

    • MenuItemcomponent={NextLink}として使用する代わりに、NextLinkMenuItemをラップ
    • passHrefプロパティを追加して、適切なリンク機能を確保
    • スタイリングを追加して、デフォルトのリンクスタイルを適切に上書き (optional)

まとめ

Next.jsとMaterial-UIの型定義の互換性問題によるエラーが発生した。
UrlObjectを用いた型定義を適切に用いる・NextLinkでMenuItemをラップすることで問題を解決した。

参考文献

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?