Importing 和 Exporting Component

Component 的神奇之處在於它的可複用性:你可以建立 component 並與其他 component 組合。但當你嵌套越來越多 component,則需要開始將它們拆分為不同的檔案。這將會提升檔案的閱讀性,也能讓 component 重複應用在更多地方。

You will learn

  • 什麼是 root component 檔案
  • 如何 import 和 export 一個 component
  • 何時使用 default 和 named import 和 export
  • 如何從一個檔案 import 和 export 多個 component
  • 如何將 component 拆分為多個檔案

root component 檔案

你的第一個 Component 中,你建立了一個 Profile component,並且 render 在 Gallery component 裡:

function Profile() {
  return (
    <img
      src="https://i.imgur.com/MK3eW3As.jpg"
      alt="Katherine Johnson"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

在此範例中,目前所有的 component 都定義在名為 App.jsroot component 檔案中。根據你的配置,root component 可能會位於其他檔案中。如果你使用像是 Next.js 這種路由基於檔案路由的框架,每個頁面的 root component 都會不一樣。

Exporting 和 importing 一個 component

如果將來你想要改變首頁,在此頁面放入科學書籍列表,或者需要將所有的資料移至其他檔案中。將 Gallery 以及 Profile 移出 root component 檔案會更加合理。這將會使它們更加模組化,並且可以在其他檔案中複用。你可以透過以下三個步驟拆分 component:

  1. 創建 一個新的 JS 檔案來存放該 component。
  2. Export 該檔案中的 component 函式(可以使用 defaultnamed export)。
  3. 在需要使用該 component 的檔案中 import(可以根據相應的 import 方式使用 defaultnamed export)。

這裡將 ProfileGalleryApp.js 檔案中移出,並放入一個名為 Gallery.js 的新檔案中。現在,你可以在 App.js import Gallery.js 中的 Gallery

import Gallery from './Gallery.js';

export default function App() {
  return (
    <Gallery />
  );
}

請注意此範例是如何將 component 拆分為兩個檔案:

  1. Gallery.js:
    • 定義了 Profile component,該 component 僅在同個檔案中使用,並沒有被 export。
    • 使用 default export 的方式, export Gallery component。
  2. App.js:
    • 使用 default import 的方式,從 Gallery.js import Gallery
    • 使用 default export 的方式,export root component App

Note

你可能會遇到沒有寫上副檔名 .js 的狀況:

import Gallery from './Gallery';

不管是 './Gallery.js' 還是 './Gallery' 都可以在 React 中運作,但前者更貼近 native ES Modules

Deep Dive

Default vs named exports

JavaScript 有兩種主要用來 export 值的方式:default export 以及 named export。 目前為止,我們的範例只有用到 default export。但你可以在同一個檔案中,選擇使用其中一種,或者兩種都使用。一個檔案中僅能有一個 default export,但可以有多個 named export

Default and named exports

Component 的 export 方式決定了其 import 方式。當你試著用 default export,import named export 的 component 將會報錯!下方圖表可以幫助你更好地理解它們:

語法Export 陳述Import 陳述
Defaultexport default function Button() {}import Button from './Button.js';
Namedexport function Button() {}import { Button } from './Button.js';

當使用 default import 時,你可以在 import 後使用任意命名。例如 import Banana from './button.js',你仍舊可以獲取一致的預設 export 內容。相反地,對於 named import,import 與 export 的名稱必須一致。這也是為什麼它們被稱為 named import!

當檔案中只需要 export 一個 component 時,人們通常會使用 default export,當檔案包含多個 component 或值需要 export 時,則會使用 named export。無論你偏好哪種方式,請記得給予 component 以及對應檔案一個有意義的命名。不建議使用未命名的 component,像是 export default () => {},這將導致除錯變得困難。

從同一檔案 export 及 import 多個 component

如果你只想要展示一個 Profile,而非整個圖集。你也可以 export Profile component。但是 Gallery.js 已經包含 default export,你不能有兩個 default export。你可以建立一個新檔案以進行 default export,或是你可以將 Profile 進行 named export。同一檔案只能有一個 default export,但可以有多個 named export!

Note

為了減少 default export 和 named export 之間的混淆,有些團隊會選擇只使用其中一種風格(default 或 named),或者避免在同一個檔案中混合使用。這因人而異,選擇最適合你的即可!

首先,使用 named export 的方式,將 ProfileGallery.js export(不使用 default 關鍵字):

export function Profile() {
// ...
}

接著,使用 named import 的方式,從 Gallery.js import ProfileApp.js(使用大括號):

import { Profile } from './Gallery.js';

最後,在 App component 中 render <Profile />

export default function App() {
return <Profile />;
}

現在 Gallery.js 包含兩個 export:一個是 default export 的 Gallery,一個是 named export 的 ProfileApp.js 都 import 了它們。請試著將下方範例中的 <Profile /> 改為 <Gallery />

import Gallery from './Gallery.js';
import { Profile } from './Gallery.js';

export default function App() {
  return (
    <Profile />
  );
}

現在,你混合使用了 default export 以及 named export:

  • Gallery.js:
    • 使用 named export 的方式,export Profile component,並命名為 Profile
    • 使用 default export 的方式,export Gallery component。
  • App.js:
    • 使用 named import 的方式,從 Gallery.js import Profile,並命名為 Profile
    • 使用 default import 的方式,從 Gallery.js import Gallery
    • 使用 default export 的方式,export root component App

Recap

在本章節中,你學到了:

  • 什麼是 root component 檔案
  • 如何 import 和 export 一個 component
  • 何時以及如何使用 default 和 named import 和 export
  • 如何將 component 拆分為多個檔案

Challenge 1 of 1:
進一步拆分 component

現在,Gallery.js 同時 export 了 ProfileGallery,這會讓人感到有些混淆。

試著將 Profile component 移至 Profile.js,然後更新 App component,依序 render <Profile /><Gallery />

你可能會使用 default export 或 named export 的方式來 export Profile,但請確保在 App.jsGallery.js 中使用了相對應的 import 語法!具體方法可參考下方表格:

語法Export 陳述Import 陳述
Defaultexport default function Button() {}import Button from './Button.js';
Namedexport function Button() {}import { Button } from './Button.js';
// Move me to Profile.js!
export function Profile() {
  return (
    <img
      src="https://i.imgur.com/QIrZWGIs.jpg"
      alt="Alan L. Hart"
    />
  );
}

export default function Gallery() {
  return (
    <section>
      <h1>Amazing scientists</h1>
      <Profile />
      <Profile />
      <Profile />
    </section>
  );
}

當你成功使用其中一種 export 方式時,請嘗試使用另一種方法實現。