はじめに
とあるNext.jsのサンプルコードを写経していて、Headerコンポーネントをimportしようとしたところ、VSCodeに怒られてimportできませんでした。
こういう時は十中八九、パスのtypoや階層構造のミスなので、入念にチェックしましたが、解決できませんでした。
原因
まず赤波線にhoverしてエラーメッセージを確認しました。
ファイル '{省略}/src/app/components/Header.tsx' はモジュールではありません。
ん? モジュールではない
ってどういうこと??
Headerコンポーネントを確認します。
const Header = () => {
return (
<header>
<div>
<h1>テスト</h1>
</div>
</header>
)
}
あ、exportしてない...
exportしてないのにimportできるはずがありません。
修正
末尾にexport default Header;
を追加しました。
const Header = () => {
return (
<header>
<div>
<h1>テスト</h1>
</div>
</header>
)
}
// 以下を追加
export default Header;
これで無事にimportできるようになりました。
ミスの原因
そもそもなぜexport default Header;
を書き落としてしまったのか。
筆者が普段以下のように、関数宣言と同時にエクスポートしているためです。
export const Header = () => {
return (
<header>
<div>
<h1>テスト</h1>
</div>
</header>
)
}
これは名前付きエクスポートという書き方です。
デフォルトエクスポートと異なり、名前付きエクスポートは複数の関数や変数をエクスポートできます。
したがって、importするときも{}
をつける必要があります。
import { Header } from "./components/Header";
ちなみに、ここで{}
を忘れるとRuntime Errorになります。
Unhandled Runtime Error
Error: Unsupported Server Component type: undefined
デフォルトエクスポート・名前付きエクスポートは、上記以外の書き方も可能です。
詳細は以下をご参照ください。
終わりに
色々試していてRuntime Error
になったときは、学習し始めたばかりのNext.jsに原因があると思いましたが、結局はJavaScriptの知識不足によるものでした。
フレームワークを扱っていると原因がどこにあるのか把握するのが大変ですが、このように根本にあるJavaScriptについて誤解しているせい、ということが多い感じです。
参考