Reactを学び始めたときにまず気付く初期の構文のいくつかは、「インポート」と「エクスポート」というフレーズを目にする事がほとんどかと思います。
これらの用語は何なのか?またReact.jsにとって非常に重要な理由は何?どの側面がそれらを必要とするのか?これらのまだ非常に新しい概念を初学者様にそれらをここで説明することになります。
エスクポートとインポートの役割と概念
インポート・エクスポートの概念は、JavaScriptのES6モジュールです。
JavaScriptのES6モジュールは、以下で詳しく解説していますので参照ください。
React.jsでインポート・エクスポートすると、モジュラーコードを記述できます。
コードを複数のファイルに分割する事が可能です。
インポートすると別のファイルのコンテンツを使用できますが、エクスポートするとファイルのコンテンツをインポートできるようになります。
これらは難しく考える必要性はありません、我々の世界でも何処かに『出入り』したりします、これと同じ事が言えます。
建物のドアを開けると別々の部屋へ分割されており、それら部屋への出入りを制御します。
建物の規模が大きいほど、個別の小さな分離が必要になります。
それら個別に分離された部屋はReactコンポーネントだと思って下さい。
JavaScriptでは、大きなファイルの必要性がそれぞれ独自の目的を持つ小さなコンポーネントの必要性を示しております。
Reactはモジュール式となります。
つまり柔軟性と適応性がありますが、アプリケーションの各部分(コンポーネント)がそれ自体に接続する方法を必要とします、情報の受け渡しは主にこれら2つのキーフレーズによって処理されます。
これは、JavaScriptモジュールで構成されていますが何かしらの方法で接続されていない限りは、各モジュールはアプリの他の部分から分離されたままになります。
インポートとエクスポートの背後にある基本的な考え方は、複数のJavaScriptファイル間で分離されたコンテンツを交換することです。
React開発者はコンポーネントを複数のファイルに分割できますがそれだけではなく必要に応じて、接続された複数のコンポーネントを1つのファイルに入れることも可能となります。
CRA(CNAも含む)を使用している場合はすでに設定がされている為、これらをすぐに使用する事が可能です。
Webpackを使用し独自でセットアップしてる場合は設定をしなければいけないことにも注意してください。
Reactエクスポートとインポート扱い方
モジュールをエクスポートするソースファイルで値が変更された時、インポートされたすべての場所で値が更新されます。
バニラJSでの、export文自体はデフォルトでは厳密モード(strict mode)のルールに従って自動的に動作しません、厳密モードを適用するには、スクリプトまたは関数の先頭に'use strict';
を追加しなければいけません。
ReactのCreate React App(CRA)では、ES6モジュールシステムを使用しており、デフォルトで厳密モード(strict mode)が有効になっています。
このため、CRAでのexport文は自動的に厳密モードのルールに従って動作します。
CRAは、Babelなどのツールを使用してコードをトランスパイルし、ブラウザで実行可能な形式に変換します。
デフォルトで有効なBabelプリセットには、"babel-preset-react-app"
が含まれており、このプリセットには厳密モードが設定されています。
したがって、Create-React-Appで作成されたReactアプリケーションでは、デフォルトで厳密モードが有効になっているため、export文や他のJavaScriptのコードも厳密モードのルールに従って動作します。
この、厳密モードの使用は一般的に推奨されており、コードの品質やセキュリティを向上させるために活用されます。
ただし、プロジェクトの一部のファイルや特定のコンポーネントで厳密モードを無効にしたい場合は、それぞれのファイルやコンポーネント内で明示的に厳密モードを無効化する必要がありますのでご注意ください。
JavaScriptのES6モジュールでは、「デフォルトエクスポート」と「名前付きエクスポート」の2つのエクスポート形式があります。
名前付きエクスポートを使用して、必要な数をエクスポートしたり、まったくエクスポートしないことも可能となります。
ファイルごとに1つのエクスポートタイプしか存在できないため、デフォルトのエクスポートはより制限されます。
まずは、名前付きエクスポート(Named Export)コンポーネントをエクスポートする例を見てみましょう。
名前付きエクスポートを使用するのは、1つのファイルの中に複数のコンポーネントがある場合となります。
export const Hello = () => { return ( <div className="App"> <h1>Hello, how are you?</h1> </div> ); } export const Reply = () => { return ( <div className="App"> <h1>Yeah, how about you?</h1> </div> ); }
これらの複数コンポーネントを別のファイルにインポートが可能となります。
// test2.jsxファイル import {Hello, Reply} from "./components/test1.jsx";
これらは名前でインポートするため、名前付きエクスポートと呼ばれます。
ソースファイルへのパスを指定します。またソースファイルと同じ名前を使用し、中括弧{}
で囲んであげます。
同じ名前という事はソースファイルと相互に関連付けている事になります、バインディング名と言います。
構文的には、中括弧はデフォルトコンポーネントではなく、名前付きインポートまたはエクスポートを表します。
名前付きエクスポートをインポートする際には、エイリアス( as
)を使用して名前を変更することができます。
これは、インポートするファイルとの名前の衝突を回避するための便利な方法です。
例えば、次のようなコードを考えてみましょう。
import {Hello as Greet} from "./components/test1.jsx";
上記の場合、"Hello"
という名前を持つエクスポートを、"Greet"
という別の名前でインポートしています。
また必ずしも、中括弧を使用する必要性はありません、代わりに、デフォルトエクスポート(Default Export)を利用します。
export default function App() { return ( <div className="App"> <h1>Hello world!</h1> </div> ); }
この場合、"App"
という名前のデフォルトエクスポートを行っています。
そして、このデフォルトエクスポートをインポートする際には、中括弧{ }
を使用せずに次のように記述します。
import Default_App from "./App.js";
ここで注目すべき点は、インポート時に中括弧を使用しないだけでなく、インポートされる名前も異なることです。
つまり、名前がバインディング名ではありません。
理由が何であれ、ファイルのパスが正しい限り、インポートされる名前を任意に変更することができます。
つまり、export defaultでは名前付きエクスポートとは異なり、柔軟性があります。
しかし、デフォルトエクスポートの唯一の欠点は、ファイルごとに1つのコンポーネントにしか適用できないことです。
名前付きエクスポートの場合では、1つのファイルの中に複数のコンポーネントがあったとしてもエクスポートが可能だったのを前述でも垣間見たはずです。
モジュールはデフォルトのエクスポートを1つだけ持つことができます、つまりシングルエクスポートです。
1つのコンポーネントにしか適応ができない例では最も分かりやすのはreact-router
を使用した場合です。
import { Routes } from "@react/router"; import My_Home from "./components/home.js"; import About from "./components/about.js"; import Contact from "./components/contact.js" const Routes = () => { return ( <Routes> <Route path="home" element={<My_Home />} /> <Route path="about" element={<About />} /> <Route path="contact" element={<Contact />} /> </Routes> ); }
しかし、デフォルトエクスポートはシングルエクスポートですが、回避策はあります。
Reactのデフォルトエクスポートでもコンポーネントをオブジェクトとしてまとめてエクスポートすることが可能です。
これにより、他のモジュールが単一のデフォルトエクスポートで複数のコンポーネントにアクセスできるようになります。
例えば、以下のようなコードを考えてみましょう。
// 子コンポーネントの定義 const ChildComponent = () => { // コンポーネントの本体 }; // 孫コンポーネントの定義 const GrandchildComponent = () => { // コンポーネントの本体 }; // コンポーネントをまとめてエクスポート export default { ChildComponent, GrandchildComponent, };
上記のコードでは、ChildComponent
とGrandchildComponent
という2つのコンポーネントをオブジェクトとしてまとめてデフォルトエクスポートしています。
他のモジュールでこれをインポートする場合、以下のようになります。
// コンポーネントのインポート import Components from './components'; // ChildComponentの使用 <Components.ChildComponent /> // GrandchildComponentの使用 <Components.GrandchildComponent />
Components
オブジェクトには、デフォルトエクスポートされたコンポーネントが含まれており、各コンポーネントはオブジェクトのプロパティとしてアクセスできます。
このようにすることで、コンポーネントを単一のデフォルトエクスポートでまとめることができ、インポート時に便利です。
ただし、コンポーネントが増える場合や複雑な構造を持つ場合には、名前付きエクスポートを使用することを検討してください。
また、デフォルトエクスポートを個別に定義する場合、var
、let
、const
キーワードを使用することはできません。
デフォルトエクスポートは、モジュールから単一の値や関数をデフォルトでエクスポートするものであり、その値や関数は名前を持ちません。
正しく言えば、export defaultとconstを同じ行で組み合わせて使用することはできません。
// ✖ export default const App = () => { // 関数の本体 };
正しい書き方は、以下のようになります。
const App = () => { return ( <div className="App"> <h1>Hello world!</h1> </div> ); } export default App //個別に定義
export default const
のような構文は許容されないため、個別の定数をデフォルトエクスポートする場合は、先に定数を宣言し、その後にexport defaultを使用してエクスポートする必要があります。
つまり、export defaultとconstの宣言を別々の文として書く必要があります。
この、個別によるデフォルトエクスポートは開発者によって意見が変わります、一部の方々には個別に定義してくれた方が読みやすいと思われる方もいらっしゃいます。
臨機応変に扱えるように心掛けて下さい。
それらを組み合わせ
デフォルトエクスポートと名前付きのエクスポートを1つのファイルに統合(組み合わせ)る事が可能です。
export const NamedComponent1 = () => {}; export const NamedComponent2 = () => {}; const DefaultComponent = () => {}; export default DefaultComponent;
インポートの際は変わりはありません、名前付きエクスポートは中括弧で囲まれ、デフォルトはそのままテキストとなります。
import DefaultComponent, { NamedComponent1, NamedComponent2 } from "./test.js"
このように、import文でデフォルトエクスポートと名前付きエクスポートを同時にインポートすることができます。
デフォルトエクスポートはimport文でデフォルトの変数名(上記の例ではDefaultComponent)を使用してインポートし、名前付きエクスポートは中括弧{}
内にインポートしたい名前付き変数(上記の例ではNamedComponent1とNamedComponent2)を列挙してインポートします。
このような形式を使うことで、同じモジュールから複数のエクスポートを一度にインポートすることができます。
Reactは、デフォルトコンポーネントと名前付きコンポーネントの両方をエクスポートするライブラリとなっております。
Reactにおいても、デフォルトエクスポートと名前付きエクスポートはモジュールの再利用性やコードの整理に役立ちます。
最後に
名前付きエクスポートを使用すると、関連する多くのコンポーネントまたはモジュールを1つのインポートとして結合できます。
デフォルトエクスポートされたコンポーネントは、インポートがはるかに簡単となります。
名前付きエクスポートとデフォルトエクスポートは、Reactからのものではありません、それらはJavaScript ES6の機能となっております。
つまり、これらはReact.jsエコシステムに与える影響という言うことになります。
ですので、名前付きエクスポートとデフォルトエクスポートのどちらを選択したとしても、あなたのアプリケーションが破損する心配はありません。
ですが違いを知っておくと、理解がより深まりソフトウェアアーキテクチャ全体とコードの可読性がさらに向上するのに役立ちます。
本日は以上となります。
最後まで読んで頂きありがとうございます。
この記事が役に立ったら、ブックマークと共有をしていただけると幸いです。