【Next.js】export default function と export default const はどっちを使うべき?
Next.js、特にApp Routerでコンポーネントを書くとき、export default functionと export default constのどちらを使うべきか悩んだことはありませんか?
この記事では、両者の明確な違いとNext.jsでのおすすめの書き方を、JavaScriptの基礎であるホイスティングも絡めて分かりやすくまとめます。
React/Next.js初心者にも理解しやすい内容にしているので、ぜひ最後まで読んでみてください。
なぜ “書き方の違い” が重要なのか?
- コンポーネントの動作が予期せず変わる
- 可読性や保守性に影響する
- TypeScript を使う場合の型推論が変わる
- チーム開発では書き方の統一が重要
特にNext.jsのApp Routerではアロー関数でコンポーネントを書くケースが増えているため、違いを理解しておくと役に立ちます。
ホイスティングの基本:この違いが2つの書き方を分ける
export default functionとexport default constの違いは、本質的には「ホイスティングされるかどうか[1]」にあります。
関数宣言(function)はホイスティングされる
console.log(greet()); // "Hello!"
function greet() {
return "Hello!";
}
関数宣言はスコープの先頭に「持ち上がる」ため、定義前に呼び出せます。
上記のコードでは、関数宣言function greet()はコードが実行される前に「持ち上げられて」関数として使える状態になるため、greet関数が呼ばれる前に宣言されています。
内部的には、JavaScriptエンジンは関数宣言を以下のように扱います:
function greet() {
return "Hello!";
}
console.log(greet()); // "Hello!"
変数宣言もホイスティングされるが、初期化はされない
変数宣言でも、変数は持ち上げられますが、初期化(値の代入)は持ち上げられません。
console.log(myVar); // undefined
var myVar = 10;
上記の例では、console.log(myVar)はundefinedを出力しますが、10にはなりません。変数宣言はホイスティングされても、初期化は実行時に行われるためです。
アロー関数(const)はホイスティングされない
constは初期化されるまで値を持たないため、定義前の呼び出しはエラーになります。
console.log(greet()); // エラー:greet is not a function
const greet = () => {
return "Hello!";
};
上記の例では、constで定義されたgreet変数は、実行時に初期化されるまで関数として利用することができません。そのため、console.log(greet())を関数定義の前で呼び出すと、エラーが発生します。
export default function と export default const の違い
export default function(関数宣言)
export default function AboutPage() {
return <h1>About</h1>;
}
特徴
- ホイスティングされる
- 伝統的な書き方でReact初期から使われている
- シンプルで読みやすい場合もある
デメリット
- 予期しないホイスティングにより挙動が分かりにくくなることがある
- 大規模プロジェクトでは可読性が下がる
- TypeScriptでは型注釈の自由度が低い
export default const(アロー関数 + 変数)
const AboutPage: React.FC = () => {
return <h1>About</h1>;
};
export default AboutPage;
特徴
- ホイスティングされず挙動が予測しやすい
- モダンなReactコンポーネント定義はアロー関数が主流
- TypeScriptで型推論しやすい
- 再代入不可のため安全(=コンポーネントを書き換えるバグを防げる)
デメリット
- 宣言より前で呼び出すことはできない
Next.js(App Router)でおすすめの書き方
結論として、Next.jsのコンポーネントはexport default const(アロー関数)がおすすめです。
結論
次の理由からexport default const(アロー関数)を使うのが最もおすすめです。
- モダンな React/Next.jsの標準的な書き方
- TypeScriptとの相性が良い
- コードの挙動が明確で安全
- 大規模開発でも保守性が高い
もしプロジェクトの規模が大きくなったりチーム開発をするなら、アロー関数で統一するとトラブルが減ります。
-
ホイスティング(持ち上げる(hoisted))とは、関数宣言や変数宣言がそのスコープの先頭に移動したように振る舞うというJavaScriptの仕組みです。 ↩︎
Discussion
export default let で宣言すれば いわゆる参照渡しで 関数をすげ替えできるので便利ですね。
(代入が import 元にも反映されるのでとても便利。もちろん import 元では 読み取り専用なので上書きされる心配もない。 ただ、代入すると 変数との参照は切れる(いわゆる値渡し)なのですげ替えはされない。